summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-10-09 13:39:51 (GMT)
committerGitHub <noreply@github.com>2023-10-09 13:39:51 (GMT)
commit7bd560ce8de41e62230975c44fd7fbd189e8e858 (patch)
tree0d58bd28ecb0827591cf0c91a0a3cefc1de1926c /Python
parentf4cb0d27cc08f490c42a22e646eb73cc7072d54a (diff)
downloadcpython-7bd560ce8de41e62230975c44fd7fbd189e8e858.zip
cpython-7bd560ce8de41e62230975c44fd7fbd189e8e858.tar.gz
cpython-7bd560ce8de41e62230975c44fd7fbd189e8e858.tar.bz2
gh-76785: Add SendChannel.send_buffer() (#110246)
(This is still a test module.)
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval_gil.c31
-rw-r--r--Python/pystate.c43
2 files changed, 45 insertions, 29 deletions
diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c
index f237e38..e269efa 100644
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -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;
}
}
diff --git a/Python/pystate.c b/Python/pystate.c
index 849a4ee..2086bd6 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -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