]> granicus.if.org Git - python/commitdiff
PyEval_SaveThread() and PyEval_RestoreThread() now return/take a
authorGuido van Rossum <guido@python.org>
Fri, 18 Jul 1997 23:56:58 +0000 (23:56 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 18 Jul 1997 23:56:58 +0000 (23:56 +0000)
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.

Include/ceval.h
Python/ceval.c

index 68c59774e9d4418d825147254342c179d8d22e07..2336ed31f45c49accf3f8ed24cf3960314e3ac86 100644 (file)
@@ -100,13 +100,16 @@ int Py_MakePendingCalls Py_PROTO((void));
 */
 
 extern void PyEval_InitThreads Py_PROTO((void));
-extern PyObject *PyEval_SaveThread Py_PROTO((void));
-extern void PyEval_RestoreThread Py_PROTO((PyObject *));
+extern PyThreadState *PyEval_SaveThread Py_PROTO((void));
+extern void PyEval_RestoreThread Py_PROTO((PyThreadState *));
 
 #ifdef WITH_THREAD
 
+extern void PyEval_AcquireThread Py_PROTO((PyThreadState *tstate));
+extern void PyEval_ReleaseThread Py_PROTO((PyThreadState *tstate));
+
 #define Py_BEGIN_ALLOW_THREADS { \
-                       PyObject *_save; \
+                       PyThreadState *_save; \
                        _save = PyEval_SaveThread();
 #define Py_BLOCK_THREADS       PyEval_RestoreThread(_save);
 #define Py_UNBLOCK_THREADS     _save = PyEval_SaveThread();
index ab1e90f2a9c4a8f4c1c008c7bcdcbf2d9a141605..be4ffec65476c9c02e6d0af4eafbbad9f24ada98 100644 (file)
@@ -135,35 +135,57 @@ PyEval_InitThreads()
    dynamically loaded modules needn't be compiled separately for use
    with and without threads: */
 
-PyObject *
+PyThreadState *
 PyEval_SaveThread()
 {
 #ifdef WITH_THREAD
        if (interpreter_lock) {
                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);
-               return res;
+               return tstate;
        }
 #endif
        return NULL;
 }
 
 void
-PyEval_RestoreThread(x)
-       PyObject *x;
+PyEval_RestoreThread(tstate)
+       PyThreadState *tstate;
 {
 #ifdef WITH_THREAD
        if (interpreter_lock) {
                int err;
                err = errno;
+               if (tstate == NULL)
+                       Py_FatalError("PyEval_RestoreThread: NULL tstate");
                acquire_lock(interpreter_lock, 1);
+               PyThreadState_Swap(tstate);
                errno = err;
-               PyThreadState_Swap(x ? ((PyFrameObject *)x)->f_tstate : NULL);
        }
 #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
    signal handlers or Mac I/O completion routines) can schedule calls