diff options
author | John Ehresman <jpe@src.gnome.org> | 2004-09-27 17:57:41 +0000 |
---|---|---|
committer | John Ehresman <jpe@src.gnome.org> | 2004-09-27 17:57:41 +0000 |
commit | 5af9d80f2cced90b86b425fd3011b5cbed3b975b (patch) | |
tree | 2c0801617d2188adb867a57f67b571bb54cef183 | |
parent | 4e66fa1cfa6d35ae97fc94a0c715abb04b79a0c3 (diff) | |
download | pygobject-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.c | 78 | ||||
-rw-r--r-- | gobject/pygobject-private.h | 11 | ||||
-rw-r--r-- | gobject/pygobject.h | 18 |
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; \ |