summaryrefslogtreecommitdiff
path: root/gtkmodule.c
diff options
context:
space:
mode:
authorJames Henstridge <james@daa.com.au>1999-07-31 15:17:13 +0000
committerJames Henstridge <jamesh@src.gnome.org>1999-07-31 15:17:13 +0000
commitb353b664618a8e4a31453a22f680e18de7d36c77 (patch)
treeb77c3f4a1bde2665d75170af819e9e8089d1f9bb /gtkmodule.c
parent88b29cb44e8e5ca3ec2e7ae774166ebc43de82be (diff)
downloadpygtk-b353b664618a8e4a31453a22f680e18de7d36c77.tar.gz
put in Paul Fisher's enhancements to the threading code. It should now
1999-07-31 James Henstridge <james@daa.com.au> * gtkmodule.c: put in Paul Fisher's enhancements to the threading code. It should now work better with multiple threads calling GTK+ routines (remember to use threads_enter/threads_leave), and doesn't reintroduce the global interpreter lock problems that Duncan's original code worked around. * configure.in: added a check for the numpy header. * GdkImlib.py: added wrappers for the numpy routines. * gdkimlibmodule.c: added Travis Oliphant's Numeric python stuff to the imlib module.
Diffstat (limited to 'gtkmodule.c')
-rw-r--r--gtkmodule.c79
1 files changed, 51 insertions, 28 deletions
diff --git a/gtkmodule.c b/gtkmodule.c
index caef5faa..dc7c2c50 100644
--- a/gtkmodule.c
+++ b/gtkmodule.c
@@ -26,25 +26,58 @@
#include "pygtk.h"
/* The threading hacks are based on ones supplied by Duncan Grisby
- * of AT&T Labs Cambridge */
+ * of AT&T Labs Cambridge. Since then they have been modified a bit. */
+
+/* The threading code has been enhanced to be a little better with multiple
+ * threads accessing GTK+. Here are some notes on the changes by
+ * Paul Fisher:
+ *
+ * If threading is enabled, we create a recursive version of Python's
+ * global interpreter mutex using TSD. This scheme makes it possible,
+ * although rather hackish, for any thread to make a call into PyGTK,
+ * as long as the GDK lock is held (that is, Python code is wrapped
+ * around a threads_{enter,leave} pair).
+ *
+ * A viable alternative would be to wrap each and every GTK call, at
+ * the Python/C level, with Py_{BEGIN,END}_ALLOW_THREADS. However,
+ * given the nature of Python threading, this option is not
+ * particularly appealing.
+ */
+
+
#ifdef WITH_THREAD
-/* this code may need to be updated if python is changed. It should work
- * for python 1.4 and 1.5.x. Check ceval.h for changes. */
-static PyThreadState *_save;
-static int _blockcount = 1;
-
-/* recusive versions of thread block and unblock routines */
-# define PyGTK_BLOCK_THREADS \
- if (_blockcount == 0) { \
- Py_BLOCK_THREADS; \
- } \
- _blockcount++;
-# define PyGTK_UNBLOCK_THREADS \
- _blockcount--; \
- if (_blockcount == 0) { \
- Py_UNBLOCK_THREADS; \
- } \
- g_assert(_blockcount >= 0);
+static GStaticPrivate pythreadstate_key = G_STATIC_PRIVATE_INIT;
+static GStaticPrivate counter_key = G_STATIC_PRIVATE_INIT;
+
+/* The global Python lock will be grabbed by Python when entering a
+ * Python/C function; thus, the initial lock count will always be one.
+ */
+# define INITIAL_LOCK_COUNT 1
+# define PyGTK_BLOCK_THREADS \
+ { \
+ gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key)); \
+ if (counter == -INITIAL_LOCK_COUNT) { \
+ PyThreadState *_save; \
+ _save = g_static_private_get(&pythreadstate_key); \
+ Py_BLOCK_THREADS; \
+ } \
+ counter++; \
+ g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL); \
+ }
+
+# define PyGTK_UNBLOCK_THREADS \
+ { \
+ gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key)); \
+ counter--; \
+ if (counter == -INITIAL_LOCK_COUNT) { \
+ PyThreadState *_save; \
+ Py_UNBLOCK_THREADS; \
+ g_static_private_set(&pythreadstate_key, _save, NULL); \
+ } \
+ g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL); \
+ }
+
+
#else /* !WITH_THREADS */
# define PyGTK_BLOCK_THREADS
# define PyGTK_UNBLOCK_THREADS
@@ -3165,10 +3198,6 @@ static PyObject *_wrap_gtk_main(PyObject *self, PyObject *args) {
PyGTK_UNBLOCK_THREADS
gtk_main();
PyGTK_BLOCK_THREADS
-#ifdef WITH_THREAD
- g_assert(_blockcount == 1);
- _blockcount = 1;
-#endif
if (PyErr_Occurred())
return NULL;
@@ -3184,10 +3213,6 @@ static PyObject *_wrap_gtk_main_iteration(PyObject *self, PyObject *args) {
PyGTK_UNBLOCK_THREADS
ret = gtk_main_iteration_do(block);
PyGTK_BLOCK_THREADS
-#ifdef WITH_THREAD
- g_assert(_blockcount == 1);
- _blockcount = 1;
-#endif
return PyInt_FromLong(ret);
}
@@ -3195,9 +3220,7 @@ static PyObject *_wrap_gtk_events_pending(PyObject *self, PyObject *args) {
int ret;
if (!PyArg_ParseTuple(args, ":gtk_events_pending"))
return NULL;
- PyGTK_UNBLOCK_THREADS
ret = gtk_events_pending();
- PyGTK_BLOCK_THREADS
return PyInt_FromLong(ret);
}