gh-110693: Pending Calls Machinery Cleanups (gh-118296)

This does some cleanup in preparation for later changes.
This commit is contained in:
Eric Snow 2024-04-25 19:05:51 -06:00 committed by GitHub
parent d5df25268b
commit 09c2947581
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 319 additions and 117 deletions

View file

@ -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);
Py_BEGIN_ALLOW_THREADS
r = Py_AddPendingCall(&_pending_callback, callable);
Py_END_ALLOW_THREADS
if (r<0) {
Py_DECREF(callable); /* unsuccessful add, destroy the extra reference */
Py_RETURN_FALSE;
for (unsigned int i = 0; i < num; i++) {
Py_INCREF(callable);
}
Py_RETURN_TRUE;
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);
}
for (unsigned int i = num_added; i < num; i++) {
Py_DECREF(callable); /* unsuccessful add, destroy the extra reference */
}
/* 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