mirror of
https://github.com/python/cpython.git
synced 2025-07-22 18:55:22 +00:00
gh-76785: Add SendChannel.send_buffer() (#110246)
(This is still a test module.)
This commit is contained in:
parent
f4cb0d27cc
commit
7bd560ce8d
13 changed files with 467 additions and 67 deletions
|
@ -663,7 +663,7 @@ _PyEval_SignalReceived(PyInterpreterState *interp)
|
|||
/* Push one item onto the queue while holding the lock. */
|
||||
static int
|
||||
_push_pending_call(struct _pending_calls *pending,
|
||||
_Py_pending_call_func func, void *arg)
|
||||
_Py_pending_call_func func, void *arg, int flags)
|
||||
{
|
||||
int i = pending->last;
|
||||
int j = (i + 1) % NPENDINGCALLS;
|
||||
|
@ -672,6 +672,7 @@ _push_pending_call(struct _pending_calls *pending,
|
|||
}
|
||||
pending->calls[i].func = func;
|
||||
pending->calls[i].arg = arg;
|
||||
pending->calls[i].flags = flags;
|
||||
pending->last = j;
|
||||
assert(pending->calls_to_do < NPENDINGCALLS);
|
||||
pending->calls_to_do++;
|
||||
|
@ -680,7 +681,7 @@ _push_pending_call(struct _pending_calls *pending,
|
|||
|
||||
static int
|
||||
_next_pending_call(struct _pending_calls *pending,
|
||||
int (**func)(void *), void **arg)
|
||||
int (**func)(void *), void **arg, int *flags)
|
||||
{
|
||||
int i = pending->first;
|
||||
if (i == pending->last) {
|
||||
|
@ -690,15 +691,16 @@ _next_pending_call(struct _pending_calls *pending,
|
|||
}
|
||||
*func = pending->calls[i].func;
|
||||
*arg = pending->calls[i].arg;
|
||||
*flags = pending->calls[i].flags;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Pop one item off the queue while holding the lock. */
|
||||
static void
|
||||
_pop_pending_call(struct _pending_calls *pending,
|
||||
int (**func)(void *), void **arg)
|
||||
int (**func)(void *), void **arg, int *flags)
|
||||
{
|
||||
int i = _next_pending_call(pending, func, arg);
|
||||
int i = _next_pending_call(pending, func, arg, flags);
|
||||
if (i >= 0) {
|
||||
pending->calls[i] = (struct _pending_call){0};
|
||||
pending->first = (i + 1) % NPENDINGCALLS;
|
||||
|
@ -714,12 +716,12 @@ _pop_pending_call(struct _pending_calls *pending,
|
|||
|
||||
int
|
||||
_PyEval_AddPendingCall(PyInterpreterState *interp,
|
||||
_Py_pending_call_func func, void *arg,
|
||||
int mainthreadonly)
|
||||
_Py_pending_call_func func, void *arg, int flags)
|
||||
{
|
||||
assert(!mainthreadonly || _Py_IsMainInterpreter(interp));
|
||||
assert(!(flags & _Py_PENDING_MAINTHREADONLY)
|
||||
|| _Py_IsMainInterpreter(interp));
|
||||
struct _pending_calls *pending = &interp->ceval.pending;
|
||||
if (mainthreadonly) {
|
||||
if (flags & _Py_PENDING_MAINTHREADONLY) {
|
||||
/* The main thread only exists in the main interpreter. */
|
||||
assert(_Py_IsMainInterpreter(interp));
|
||||
pending = &_PyRuntime.ceval.pending_mainthread;
|
||||
|
@ -729,7 +731,7 @@ _PyEval_AddPendingCall(PyInterpreterState *interp,
|
|||
assert(pending->lock != NULL);
|
||||
|
||||
PyThread_acquire_lock(pending->lock, WAIT_LOCK);
|
||||
int result = _push_pending_call(pending, func, arg);
|
||||
int result = _push_pending_call(pending, func, arg, flags);
|
||||
PyThread_release_lock(pending->lock);
|
||||
|
||||
/* signal main loop */
|
||||
|
@ -743,7 +745,7 @@ Py_AddPendingCall(_Py_pending_call_func func, void *arg)
|
|||
/* Legacy users of this API will continue to target the main thread
|
||||
(of the main interpreter). */
|
||||
PyInterpreterState *interp = _PyInterpreterState_Main();
|
||||
return _PyEval_AddPendingCall(interp, func, arg, 1);
|
||||
return _PyEval_AddPendingCall(interp, func, arg, _Py_PENDING_MAINTHREADONLY);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -769,17 +771,22 @@ _make_pending_calls(struct _pending_calls *pending)
|
|||
for (int i=0; i<NPENDINGCALLS; i++) {
|
||||
_Py_pending_call_func func = NULL;
|
||||
void *arg = NULL;
|
||||
int flags = 0;
|
||||
|
||||
/* pop one item off the queue while holding the lock */
|
||||
PyThread_acquire_lock(pending->lock, WAIT_LOCK);
|
||||
_pop_pending_call(pending, &func, &arg);
|
||||
_pop_pending_call(pending, &func, &arg, &flags);
|
||||
PyThread_release_lock(pending->lock);
|
||||
|
||||
/* having released the lock, perform the callback */
|
||||
if (func == NULL) {
|
||||
break;
|
||||
}
|
||||
if (func(arg) != 0) {
|
||||
int res = func(arg);
|
||||
if ((flags & _Py_PENDING_RAWFREE) && arg != NULL) {
|
||||
PyMem_RawFree(arg);
|
||||
}
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2584,18 +2584,36 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
|
|||
return data->new_object(data);
|
||||
}
|
||||
|
||||
static int
|
||||
_release_xidata_pending(void *data)
|
||||
int
|
||||
_Py_CallInInterpreter(PyInterpreterState *interp,
|
||||
_Py_simple_func func, void *arg)
|
||||
{
|
||||
_xidata_clear((_PyCrossInterpreterData *)data);
|
||||
if (interp == current_fast_get(interp->runtime)->interp) {
|
||||
return func(arg);
|
||||
}
|
||||
// XXX Emit a warning if this fails?
|
||||
_PyEval_AddPendingCall(interp, (_Py_pending_call_func)func, arg, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_Py_CallInInterpreterAndRawFree(PyInterpreterState *interp,
|
||||
_Py_simple_func func, void *arg)
|
||||
{
|
||||
if (interp == current_fast_get(interp->runtime)->interp) {
|
||||
int res = func(arg);
|
||||
PyMem_RawFree(arg);
|
||||
return res;
|
||||
}
|
||||
// XXX Emit a warning if this fails?
|
||||
_PyEval_AddPendingCall(interp, func, arg, _Py_PENDING_RAWFREE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_xidata_release_and_rawfree_pending(void *data)
|
||||
_call_clear_xidata(void *data)
|
||||
{
|
||||
_xidata_clear((_PyCrossInterpreterData *)data);
|
||||
PyMem_RawFree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2627,21 +2645,12 @@ _xidata_release(_PyCrossInterpreterData *data, int rawfree)
|
|||
}
|
||||
|
||||
// "Release" the data and/or the object.
|
||||
if (interp == current_fast_get(interp->runtime)->interp) {
|
||||
_xidata_clear(data);
|
||||
if (rawfree) {
|
||||
PyMem_RawFree(data);
|
||||
}
|
||||
if (rawfree) {
|
||||
return _Py_CallInInterpreterAndRawFree(interp, _call_clear_xidata, data);
|
||||
}
|
||||
else {
|
||||
_Py_pending_call_func func = _release_xidata_pending;
|
||||
if (rawfree) {
|
||||
func = _xidata_release_and_rawfree_pending;
|
||||
}
|
||||
// XXX Emit a warning if this fails?
|
||||
_PyEval_AddPendingCall(interp, func, data, 0);
|
||||
return _Py_CallInInterpreter(interp, _call_clear_xidata, data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue