diff options
author | Kristján Valur Jónsson <kristjan@ccpgames.com> | 2009-01-09 21:35:16 (GMT) |
---|---|---|
committer | Kristján Valur Jónsson <kristjan@ccpgames.com> | 2009-01-09 21:35:16 (GMT) |
commit | 0e2d8c36e3b52b7ff9d2926d1c2ad4be9df84710 (patch) | |
tree | cdfe6ca9439994206d86af13cc247383affeec8a /Modules | |
parent | 0e91938e5851173821f917bf19157dde5f946c09 (diff) | |
download | cpython-0e2d8c36e3b52b7ff9d2926d1c2ad4be9df84710.zip cpython-0e2d8c36e3b52b7ff9d2926d1c2ad4be9df84710.tar.gz cpython-0e2d8c36e3b52b7ff9d2926d1c2ad4be9df84710.tar.bz2 |
Issue 4293: Make Py_AddPendingCall() thread safe
Add test cases and documentation
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_testcapimodule.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 665d375..1475f72 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -837,6 +837,43 @@ test_thread_state(PyObject *self, PyObject *args) return NULL; Py_RETURN_NONE; } + +/* test Py_AddPendingCalls using threads */ +static int _pending_callback(void *arg) +{ + /* we assume the argument is callable object to which we own a reference */ + PyObject *callable = (PyObject *)arg; + PyObject *r = PyObject_CallObject(callable, NULL); + Py_DECREF(callable); + Py_XDECREF(r); + return r != NULL ? 0 : -1; +} + +/* The following requests n callbacks to _pending_callback. It can be + * run from any python thread. + */ +PyObject *pending_threadfunc(PyObject *self, PyObject *arg) +{ + PyObject *callable; + int r; + if (PyArg_ParseTuple(arg, "O", &callable) == 0) + 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_INCREF(Py_False); + return Py_False; + } + Py_INCREF(Py_True); + return Py_True; +} #endif /* Some tests of PyString_FromFormat(). This needs more tests. */ @@ -941,6 +978,7 @@ static PyMethodDef TestMethods[] = { #endif #ifdef WITH_THREAD {"_test_thread_state", test_thread_state, METH_VARARGS}, + {"_pending_threadfunc", pending_threadfunc, METH_VARARGS}, #endif {"traceback_print", traceback_print, METH_VARARGS}, {NULL, NULL} /* sentinel */ |