mirror of
https://github.com/python/cpython.git
synced 2025-09-25 01:43:11 +00:00
PyEval_SaveThread() and PyEval_RestoreThread() now return/take a
PyThreadState pointer instead of a (frame) PyObject pointer. This makes much more sense. It is backward incompatible, but that's no problem, because (a) the heaviest users are the Py_{BEGIN,END}_ ALLOW_THREADS macros here, which have been fixed too; (b) there are very few direct users; (c) those who use it are there will probably appreciate the change. Also, added new functions PyEval_AcquireThread() and PyEval_ReleaseThread() which allows the threads created by the thread module as well threads created by others (!) to set/reset the current thread, and at the same time acquire/release the interpreter lock. Much saner.
This commit is contained in:
parent
c864ad695f
commit
2fca21f762
2 changed files with 34 additions and 9 deletions
|
@ -100,13 +100,16 @@ int Py_MakePendingCalls Py_PROTO((void));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void PyEval_InitThreads Py_PROTO((void));
|
extern void PyEval_InitThreads Py_PROTO((void));
|
||||||
extern PyObject *PyEval_SaveThread Py_PROTO((void));
|
extern PyThreadState *PyEval_SaveThread Py_PROTO((void));
|
||||||
extern void PyEval_RestoreThread Py_PROTO((PyObject *));
|
extern void PyEval_RestoreThread Py_PROTO((PyThreadState *));
|
||||||
|
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
|
|
||||||
|
extern void PyEval_AcquireThread Py_PROTO((PyThreadState *tstate));
|
||||||
|
extern void PyEval_ReleaseThread Py_PROTO((PyThreadState *tstate));
|
||||||
|
|
||||||
#define Py_BEGIN_ALLOW_THREADS { \
|
#define Py_BEGIN_ALLOW_THREADS { \
|
||||||
PyObject *_save; \
|
PyThreadState *_save; \
|
||||||
_save = PyEval_SaveThread();
|
_save = PyEval_SaveThread();
|
||||||
#define Py_BLOCK_THREADS PyEval_RestoreThread(_save);
|
#define Py_BLOCK_THREADS PyEval_RestoreThread(_save);
|
||||||
#define Py_UNBLOCK_THREADS _save = PyEval_SaveThread();
|
#define Py_UNBLOCK_THREADS _save = PyEval_SaveThread();
|
||||||
|
|
|
@ -135,35 +135,57 @@ PyEval_InitThreads()
|
||||||
dynamically loaded modules needn't be compiled separately for use
|
dynamically loaded modules needn't be compiled separately for use
|
||||||
with and without threads: */
|
with and without threads: */
|
||||||
|
|
||||||
PyObject *
|
PyThreadState *
|
||||||
PyEval_SaveThread()
|
PyEval_SaveThread()
|
||||||
{
|
{
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
if (interpreter_lock) {
|
if (interpreter_lock) {
|
||||||
PyThreadState *tstate = PyThreadState_Swap(NULL);
|
PyThreadState *tstate = PyThreadState_Swap(NULL);
|
||||||
PyObject *res = tstate ? (PyObject *) (tstate->frame) : NULL;
|
if (tstate == NULL)
|
||||||
|
Py_FatalError("PyEval_SaveThread: NULL tstate");
|
||||||
release_lock(interpreter_lock);
|
release_lock(interpreter_lock);
|
||||||
return res;
|
return tstate;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PyEval_RestoreThread(x)
|
PyEval_RestoreThread(tstate)
|
||||||
PyObject *x;
|
PyThreadState *tstate;
|
||||||
{
|
{
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
if (interpreter_lock) {
|
if (interpreter_lock) {
|
||||||
int err;
|
int err;
|
||||||
err = errno;
|
err = errno;
|
||||||
|
if (tstate == NULL)
|
||||||
|
Py_FatalError("PyEval_RestoreThread: NULL tstate");
|
||||||
acquire_lock(interpreter_lock, 1);
|
acquire_lock(interpreter_lock, 1);
|
||||||
|
PyThreadState_Swap(tstate);
|
||||||
errno = err;
|
errno = err;
|
||||||
PyThreadState_Swap(x ? ((PyFrameObject *)x)->f_tstate : NULL);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_THREAD
|
||||||
|
void
|
||||||
|
PyEval_AcquireThread(tstate)
|
||||||
|
PyThreadState *tstate;
|
||||||
|
{
|
||||||
|
acquire_lock(interpreter_lock, 1);
|
||||||
|
if (PyThreadState_Swap(tstate) != NULL)
|
||||||
|
Py_FatalError("PyEval_AcquireThread: non-NULL old state");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PyEval_ReleaseThread(tstate)
|
||||||
|
PyThreadState *tstate;
|
||||||
|
{
|
||||||
|
if (PyThreadState_Swap(NULL) != tstate)
|
||||||
|
Py_FatalError("PyEval_ReleaseThread: wrong thread state");
|
||||||
|
release_lock(interpreter_lock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX
|
/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX
|
||||||
signal handlers or Mac I/O completion routines) can schedule calls
|
signal handlers or Mac I/O completion routines) can schedule calls
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue