summaryrefslogtreecommitdiffstats
path: root/Modules/_testinternalcapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_testinternalcapi.c')
-rw-r--r--Modules/_testinternalcapi.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index cc9e140..b0bba34 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -1062,37 +1062,56 @@ static PyObject *
pending_threadfunc(PyObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *callable;
+ unsigned int num = 1;
+ int blocking = 0;
int ensure_added = 0;
- static char *kwlist[] = {"", "ensure_added", NULL};
+ static char *kwlist[] = {"callback", "num",
+ "blocking", "ensure_added", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O|$p:pending_threadfunc", kwlist,
- &callable, &ensure_added))
+ "O|I$pp:pending_threadfunc", kwlist,
+ &callable, &num, &blocking, &ensure_added))
{
return NULL;
}
PyInterpreterState *interp = _PyInterpreterState_GET();
/* create the reference for the callbackwhile we hold the lock */
- Py_INCREF(callable);
+ for (unsigned int i = 0; i < num; i++) {
+ Py_INCREF(callable);
+ }
- int r;
- Py_BEGIN_ALLOW_THREADS
- r = _PyEval_AddPendingCall(interp, &_pending_callback, callable, 0);
- Py_END_ALLOW_THREADS
- if (r < 0) {
- /* unsuccessful add */
- if (!ensure_added) {
- Py_DECREF(callable);
- Py_RETURN_FALSE;
+ PyThreadState *save_tstate = NULL;
+ if (!blocking) {
+ save_tstate = PyEval_SaveThread();
+ }
+
+ unsigned int num_added = 0;
+ for (; num_added < num; num_added++) {
+ if (ensure_added) {
+ _Py_add_pending_call_result r;
+ do {
+ r = _PyEval_AddPendingCall(interp, &_pending_callback, callable, 0);
+ assert(r == _Py_ADD_PENDING_SUCCESS
+ || r == _Py_ADD_PENDING_FULL);
+ } while (r == _Py_ADD_PENDING_FULL);
+ }
+ else {
+ if (_PyEval_AddPendingCall(interp, &_pending_callback, callable, 0) < 0) {
+ break;
+ }
}
- do {
- Py_BEGIN_ALLOW_THREADS
- r = _PyEval_AddPendingCall(interp, &_pending_callback, callable, 0);
- Py_END_ALLOW_THREADS
- } while (r < 0);
}
- Py_RETURN_TRUE;
+ 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 in _pending_callback() above. */
+ return PyLong_FromUnsignedLong((unsigned long)num_added);
}
@@ -1135,14 +1154,16 @@ pending_identify(PyObject *self, PyObject *args)
PyThread_acquire_lock(mutex, WAIT_LOCK);
/* It gets released in _pending_identify_callback(). */
- int r;
+ _Py_add_pending_call_result r;
do {
Py_BEGIN_ALLOW_THREADS
r = _PyEval_AddPendingCall(interp,
&_pending_identify_callback, (void *)mutex,
0);
Py_END_ALLOW_THREADS
- } while (r < 0);
+ assert(r == _Py_ADD_PENDING_SUCCESS
+ || r == _Py_ADD_PENDING_FULL);
+ } while (r == _Py_ADD_PENDING_FULL);
/* Wait for the pending call to complete. */
PyThread_acquire_lock(mutex, WAIT_LOCK);