summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Ehresman <jpe@src.gnome.org>2004-09-27 17:57:41 +0000
committerJohn Ehresman <jpe@src.gnome.org>2004-09-27 17:57:41 +0000
commit5af9d80f2cced90b86b425fd3011b5cbed3b975b (patch)
tree2c0801617d2188adb867a57f67b571bb54cef183
parent4e66fa1cfa6d35ae97fc94a0c715abb04b79a0c3 (diff)
downloadpygobject-5af9d80f2cced90b86b425fd3011b5cbed3b975b.tar.gz
pygobject-5af9d80f2cced90b86b425fd3011b5cbed3b975b.tar.xz
pygobject-5af9d80f2cced90b86b425fd3011b5cbed3b975b.zip
New functions exposed through _PyGObject_Functions to work around bugs in
* gobject/gobjectmodule.c: New functions exposed through _PyGObject_Functions to work around bugs in the PyGILState api's * gobject/pygobject.h: idem * gobject/pygobject-private.h: idem * gtk/gtk.override (_wrap_gtk_main): add pyg_enable_threads() call to ensure thread state for thread invoking this function is remembered. Only call pyg_enable_threads() here if threads were previously enabled
-rw-r--r--gobject/gobjectmodule.c78
-rw-r--r--gobject/pygobject-private.h11
-rw-r--r--gobject/pygobject.h18
3 files changed, 102 insertions, 5 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index 2dfd990..f6db634 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -25,6 +25,7 @@
#endif
#include "pygobject-private.h"
+#include "pythread.h"
static PyObject *gerror_exc = NULL;
static const gchar *pyginterface_type_id = "PyGInterface::type";
@@ -1454,14 +1455,29 @@ pyg_main_context_default (PyObject *unused)
}
+static int pyg_thread_state_tls_key = -1;
+
static int
pyg_enable_threads (void)
{
#ifndef DISABLE_THREADING
- PyEval_InitThreads();
- if (!g_threads_got_initialized)
- g_thread_init(NULL);
- pygobject_api_functions.threads_enabled = TRUE;
+ if (!pygobject_api_functions.threads_enabled) {
+ PyEval_InitThreads();
+ if (!g_threads_got_initialized)
+ g_thread_init(NULL);
+ pygobject_api_functions.threads_enabled = TRUE;
+ pyg_thread_state_tls_key = PyThread_create_key();
+ }
+
+#ifdef PYGIL_API_IS_BUGGY
+ {
+ PyThreadState* state;
+ state = PyGILState_GetThisThreadState();
+ if ( state != NULL )
+ PyThread_set_key_value(pyg_thread_state_tls_key, state);
+ }
+#endif
+
return 0;
#else
PyErr_SetString(PyExc_RuntimeError,
@@ -1470,6 +1486,56 @@ pyg_enable_threads (void)
#endif
}
+static PyThreadState *
+pyg_find_thread_state (void)
+{
+ PyThreadState* state;
+
+ if (pyg_thread_state_tls_key == -1)
+ return NULL;
+ state = PyThread_get_key_value(pyg_thread_state_tls_key);
+ if ( state == NULL ) {
+ state = PyGILState_GetThisThreadState();
+ if ( state != NULL )
+ PyThread_set_key_value(pyg_thread_state_tls_key, state);
+ }
+ return state;
+}
+
+static int
+pyg_gil_state_ensure_py23 (void)
+{
+#ifndef PYGIL_API_IS_BUGGY
+ return PyGILState_Ensure();
+#else
+ PyThreadState* state = pyg_find_thread_state();
+
+ if ( state == NULL )
+ return PyGILState_LOCKED;
+
+ if ( state == _PyThreadState_Current )
+ return PyGILState_LOCKED;
+ else {
+ PyEval_RestoreThread(state);
+ return PyGILState_UNLOCKED;
+ }
+#endif
+}
+
+static void
+pyg_gil_state_release_py23 (int flag)
+{
+#ifndef PYGIL_API_IS_BUGGY
+ PyGILState_Release(flag);
+#else
+ if (flag == PyGILState_UNLOCKED) {
+ PyThreadState* state = pyg_find_thread_state();
+ if ( state != NULL )
+ PyEval_ReleaseThread(state);
+ }
+#endif
+}
+
static PyObject *
pyg_threads_init (PyObject *unused)
{
@@ -1811,7 +1877,9 @@ struct _PyGObject_Functions pygobject_api_functions = {
pyg_flags_from_gtype,
FALSE, /* threads_enabled */
- pyg_enable_threads
+ pyg_enable_threads,
+ pyg_gil_state_ensure_py23,
+ pyg_gil_state_release_py23
};
#define REGISTER_TYPE(d, type, name) \
diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h
index e74ec0a..eb4b107 100644
--- a/gobject/pygobject-private.h
+++ b/gobject/pygobject-private.h
@@ -20,11 +20,22 @@ extern struct _PyGObject_Functions pygobject_api_functions;
} G_STMT_END
#define pyg_threads_enabled (pygobject_api_functions.threads_enabled)
+
+#ifndef PYGIL_API_IS_BUGGY
#define pyg_gil_state_ensure() (pygobject_api_functions.threads_enabled? (PyGILState_Ensure()) : 0)
#define pyg_gil_state_release(state) G_STMT_START { \
if (pygobject_api_functions.threads_enabled) \
PyGILState_Release(state); \
} G_STMT_END
+#else
+#define pyg_gil_state_ensure() (pygobject_api_functions.threads_enabled? (pygobject_api_functions.gil_state_ensure()) : 0)
+#define pyg_gil_state_release(state) G_STMT_START { \
+ if (pygobject_api_functions.threads_enabled) \
+ pygobject_api_functions.gil_state_release(state); \
+ } G_STMT_END
+
+#endif
+
#define pyg_begin_allow_threads \
G_STMT_START { \
PyThreadState *_save = NULL; \
diff --git a/gobject/pygobject.h b/gobject/pygobject.h
index 14a83c2..4c99031 100644
--- a/gobject/pygobject.h
+++ b/gobject/pygobject.h
@@ -7,6 +7,11 @@
#include <glib.h>
#include <glib-object.h>
+/* Work around bugs in PyGILState api fixed in 2.4.0a4 */
+#if PY_HEXVERSION < 0x020400A4
+#define PYGIL_API_IS_BUGGY
+#endif
+
/* PyGClosure is a _private_ structure */
typedef struct _PyGClosure PyGClosure;
struct _PyGClosure {
@@ -144,6 +149,8 @@ struct _PyGObject_Functions {
gboolean threads_enabled;
int (*enable_threads) (void);
+ int (*gil_state_ensure) (void);
+ void (*gil_state_release) (int flag);
};
#ifndef _INSIDE_PYGOBJECT_
@@ -206,11 +213,22 @@ struct _PyGObject_Functions *_PyGObject_API;
} G_STMT_END
#define pyg_threads_enabled (_PyGObject_API->threads_enabled)
+
+#ifndef PYGIL_API_IS_BUGGY
#define pyg_gil_state_ensure() (_PyGObject_API->threads_enabled? (PyGILState_Ensure()) : 0)
#define pyg_gil_state_release(state) G_STMT_START { \
if (_PyGObject_API->threads_enabled) \
PyGILState_Release(state); \
} G_STMT_END
+#else
+#define pyg_gil_state_ensure() (_PyGObject_API->threads_enabled? (_PyGObject_API->gil_state_ensure()) : 0)
+#define pyg_gil_state_release(state) G_STMT_START { \
+ if (_PyGObject_API->threads_enabled) \
+ _PyGObject_API->gil_state_release(state); \
+ } G_STMT_END
+
+#endif
+
#define pyg_begin_allow_threads \
G_STMT_START { \
PyThreadState *_save = NULL; \