summaryrefslogtreecommitdiffstats
path: root/Modules/_testcapimodule.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2024-04-26 01:05:51 (GMT)
committerGitHub <noreply@github.com>2024-04-26 01:05:51 (GMT)
commit09c29475813ff2a763931fc0b45aaaef57cd2ac7 (patch)
treedc006bd73c8969f5a228a3b778c38349b3cc8bbb /Modules/_testcapimodule.c
parentd5df25268b037c2f1f4a1184fad5274d0e72f8d6 (diff)
downloadcpython-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.c53
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