diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2024-04-26 01:05:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-26 01:05:51 (GMT) |
commit | 09c29475813ff2a763931fc0b45aaaef57cd2ac7 (patch) | |
tree | dc006bd73c8969f5a228a3b778c38349b3cc8bbb /Modules/_testcapimodule.c | |
parent | d5df25268b037c2f1f4a1184fad5274d0e72f8d6 (diff) | |
download | cpython-09c29475813ff2a763931fc0b45aaaef57cd2ac7.zip cpython-09c29475813ff2a763931fc0b45aaaef57cd2ac7.tar.gz cpython-09c29475813ff2a763931fc0b45aaaef57cd2ac7.tar.bz2 |
gh-110693: Pending Calls Machinery Cleanups (gh-118296)
This does some cleanup in preparation for later changes.
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r-- | Modules/_testcapimodule.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 034a30fa..0bdd252 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -819,25 +819,55 @@ static int _pending_callback(void *arg) * run from any python thread. */ static PyObject * -pending_threadfunc(PyObject *self, PyObject *arg) +pending_threadfunc(PyObject *self, PyObject *arg, PyObject *kwargs) { + static char *kwlist[] = {"callback", "num", + "blocking", "ensure_added", NULL}; PyObject *callable; - int r; - if (PyArg_ParseTuple(arg, "O", &callable) == 0) + unsigned int num = 1; + int blocking = 0; + int ensure_added = 0; + if (!PyArg_ParseTupleAndKeywords(arg, kwargs, + "O|I$pp:_pending_threadfunc", kwlist, + &callable, &num, &blocking, &ensure_added)) + { return NULL; + } /* create the reference for the callbackwhile we hold the lock */ - Py_INCREF(callable); + for (unsigned int i = 0; i < num; i++) { + Py_INCREF(callable); + } - Py_BEGIN_ALLOW_THREADS - r = Py_AddPendingCall(&_pending_callback, callable); - Py_END_ALLOW_THREADS + PyThreadState *save_tstate = NULL; + if (!blocking) { + save_tstate = PyEval_SaveThread(); + } + + unsigned int num_added = 0; + for (; num_added < num; num_added++) { + if (ensure_added) { + int r; + do { + r = Py_AddPendingCall(&_pending_callback, callable); + } while (r < 0); + } + else { + if (Py_AddPendingCall(&_pending_callback, callable) < 0) { + break; + } + } + } + + if (!blocking) { + PyEval_RestoreThread(save_tstate); + } - if (r<0) { + for (unsigned int i = num_added; i < num; i++) { Py_DECREF(callable); /* unsuccessful add, destroy the extra reference */ - Py_RETURN_FALSE; } - Py_RETURN_TRUE; + /* The callable is decref'ed above in each added _pending_callback(). */ + return PyLong_FromUnsignedLong((unsigned long)num_added); } /* Test PyOS_string_to_double. */ @@ -3232,7 +3262,8 @@ static PyMethodDef TestMethods[] = { {"_spawn_pthread_waiter", spawn_pthread_waiter, METH_NOARGS}, {"_end_spawned_pthread", end_spawned_pthread, METH_NOARGS}, #endif - {"_pending_threadfunc", pending_threadfunc, METH_VARARGS}, + {"_pending_threadfunc", _PyCFunction_CAST(pending_threadfunc), + METH_VARARGS|METH_KEYWORDS}, #ifdef HAVE_GETTIMEOFDAY {"profile_int", profile_int, METH_NOARGS}, #endif |