diff options
author | James Henstridge <james@daa.com.au> | 2002-01-07 02:31:41 +0000 |
---|---|---|
committer | James Henstridge <jamesh@src.gnome.org> | 2002-01-07 02:31:41 +0000 |
commit | 5061a6345c6458d591f24a3d75c671bfff83814a (patch) | |
tree | fbc854dc1183af035f2564ad77f60bc41a705749 | |
parent | a8285608c598b2097676e3e1c8252d76fb297c4a (diff) | |
download | pygobject-5061a6345c6458d591f24a3d75c671bfff83814a.tar.gz pygobject-5061a6345c6458d591f24a3d75c671bfff83814a.tar.xz pygobject-5061a6345c6458d591f24a3d75c671bfff83814a.zip |
handler for registering thread block/unblock funcs.
2002-01-07 James Henstridge <james@daa.com.au>
* gobjectmodule.c (pyg_set_thread_block_funcs): handler for
registering thread block/unblock funcs.
(pygobject_destroy_notify): block threads during DECREF call.
(pyg_closure_destroy): block threads during closure DECREF.
(pyg_closure_marshal): block threads when calling function.
(pyg_signal_class_closure_marshal): block threads.
(functions): add extra functions to vtable.
* pygobject.h (struct _PyGObject_Functions): add thread
block/unblock slots to the API table.
-rw-r--r-- | gobject/gobjectmodule.c | 58 | ||||
-rw-r--r-- | gobject/pygobject.h | 19 |
2 files changed, 67 insertions, 10 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index 8c027d0..1e61fd2 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -1,4 +1,9 @@ /* -*- Mode: C; c-basic-offset: 4 -*- */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + #define _INSIDE_PYGOBJECT_ #include "pygobject.h" @@ -16,6 +21,29 @@ static int pygobject_traverse(PyGObject *self, visitproc visit, void *arg); static int pyg_fatal_exceptions_notify(void); + +/* -------------- GDK threading hooks ---------------------------- */ + +staticforward struct _PyGObject_Functions functions; +#define pyg_block_threads() G_STMT_START { \ + if (functions.block_threads != NULL) \ + (* functions.block_threads)(); \ + } G_STMT_END +#define pyg_unblock_threads() G_STMT_START { \ + if (functions.unblock_threads != NULL) \ + (* functions.unblock_threads)(); \ + } G_STMT_END + +static void +pyg_set_thread_block_funcs (PyGThreadBlockFunc block_threads_func, + PyGThreadBlockFunc unblock_threads_func) +{ + g_return_if_fail(functions.block_threads == NULL && functions.unblock_threads == NULL); + + functions.block_threads = block_threads_func; + functions.unblock_threads = unblock_threads_func; +} + static void object_free(PyObject *op) { @@ -226,9 +254,9 @@ pygobject_destroy_notify(gpointer user_data) { PyObject *obj = (PyObject *)user_data; - /* PyGTK_BLOCK_THREADS */ + pyg_block_threads(); Py_DECREF(obj); - /* PyGTK_UNBLOCK_THREADS */ + pyg_unblock_threads(); } static void @@ -989,15 +1017,16 @@ struct _PyGClosure { PyObject *swap_data; /* other object for gtk_signal_connect_object */ }; -/* XXXX - must handle multithreadedness here */ static void pyg_closure_destroy(gpointer data, GClosure *closure) { PyGClosure *pc = (PyGClosure *)closure; + pyg_block_threads(); Py_DECREF(pc->callback); Py_XDECREF(pc->extra_args); Py_XDECREF(pc->swap_data); + pyg_unblock_threads(); } /* XXXX - need to handle python thread context stuff */ @@ -1013,6 +1042,7 @@ pyg_closure_marshal(GClosure *closure, PyObject *params, *ret; guint i; + pyg_block_threads(); /* construct Python tuple for the parameter values */ params = PyTuple_New(n_param_values); for (i = 0; i < n_param_values; i++) { @@ -1027,7 +1057,7 @@ pyg_closure_marshal(GClosure *closure, /* error condition */ if (!item) { Py_DECREF(params); - /* XXXX - clean up if threading was used */ + pyg_unblock_threads(); return; } PyTuple_SetItem(params, i, item); @@ -1043,12 +1073,13 @@ pyg_closure_marshal(GClosure *closure, if (ret == NULL) { PyErr_Print(); PyErr_Clear(); + pyg_unblock_threads(); return; } if (return_value) pyg_value_from_pyobject(return_value, ret); Py_DECREF(ret); - /* XXXX - clean up if threading was used */ + pyg_unblock_threads(); } static GClosure * @@ -1062,7 +1093,7 @@ pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data) g_closure_set_marshal(closure, pyg_closure_marshal); Py_INCREF(callback); ((PyGClosure *)closure)->callback = callback; - if (extra_args) { + if (extra_args && extra_args != Py_None) { if (!PyTuple_Check(extra_args)) { PyObject *tmp = PyTuple_New(1); PySequence_SetItem(tmp, 0, extra_args); @@ -1109,6 +1140,7 @@ pyg_signal_class_closure_marshal(GClosure *closure, g_return_if_fail(invocation_hint != NULL); + pyg_block_threads(); /* get the object passed as the first argument to the closure */ object = g_value_get_object(¶m_values[0]); g_return_if_fail(object != NULL && G_IS_OBJECT(object)); @@ -1132,6 +1164,7 @@ pyg_signal_class_closure_marshal(GClosure *closure, if (!method) { PyErr_Clear(); Py_DECREF(object_wrapper); + pyg_unblock_threads(); return; } Py_DECREF(object_wrapper); @@ -1144,7 +1177,7 @@ pyg_signal_class_closure_marshal(GClosure *closure, /* error condition */ if (!item) { Py_DECREF(params); - /* XXXX - clean up if threading was used */ + pyg_unblock_threads(); return; } PyTuple_SetItem(params, i - 1, item); @@ -1154,15 +1187,15 @@ pyg_signal_class_closure_marshal(GClosure *closure, if (ret == NULL) { PyErr_Print(); PyErr_Clear(); - /* XXXX - clean up if threading was used */ Py_DECREF(method); + pyg_unblock_threads(); return; } Py_DECREF(method); if (return_value) pyg_value_from_pyobject(return_value, ret); Py_DECREF(ret); - /* XXXX - clean up if threading was used */ + pyg_unblock_threads(); } static GClosure * @@ -1662,6 +1695,7 @@ pygobject_emit(PyGObject *self, PyObject *args) } if (query.return_type != G_TYPE_NONE) g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); + g_signal_emitv(params, signal_id, detail, &ret); for (i = 0; i < query.n_params + 1; i++) g_value_unset(¶ms[i]); @@ -1701,7 +1735,7 @@ pygobject_chain_from_overridden(PyGObject *self, PyObject *args) GSignalInvocationHint *ihint; guint signal_id, i, len; PyObject *first, *py_ret; - gchar *name; + const gchar *name; GSignalQuery query; GValue *params, ret = { 0, }; @@ -2989,6 +3023,10 @@ static struct _PyGObject_Functions functions = { pyg_constant_strip_prefix, pyg_error_check, + + pyg_set_thread_block_funcs, + (PyGThreadBlockFunc)0, /* block_threads */ + (PyGThreadBlockFunc)0, /* unblock_threads */ }; DL_EXPORT(void) diff --git a/gobject/pygobject.h b/gobject/pygobject.h index 99aa796..8fa4542 100644 --- a/gobject/pygobject.h +++ b/gobject/pygobject.h @@ -29,6 +29,7 @@ typedef struct { #define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode) typedef void (*PyGFatalExceptionFunc) (void); +typedef void (*PyGThreadBlockFunc) (void); struct _PyGObject_Functions { void (* register_class)(PyObject *dict, const gchar *class_name, @@ -68,6 +69,13 @@ struct _PyGObject_Functions { const gchar *strip_prefix); gboolean (* error_check)(GError **error); + + /* hooks to register handlers for getting GDK threads to cooperate + * with python threading */ + void (* set_thread_block_funcs) (PyGThreadBlockFunc block_threads_func, + PyGThreadBlockFunc unblock_threads_func); + PyGThreadBlockFunc block_threads; + PyGThreadBlockFunc unblock_threads; }; #ifndef _INSIDE_PYGOBJECT_ @@ -98,6 +106,17 @@ struct _PyGObject_Functions *_PyGObject_API; #define pyg_flags_add_constants (_PyGObject_API->flags_add_constants) #define pyg_constant_strip_prefix (_PyGObject_API->constant_strip_prefix) #define pyg_error_check (_PyGObject_API->error_check) +#define pyg_set_thread_block_funcs (_PyGObject_API->set_thread_block_funcs) + +#define pyg_block_threads() G_STMT_START { \ + if (_PyGObject_API->block_threads != NULL) \ + (* _PyGObject_API->block_threads)(); \ + } G_STMT_END +#define pyg_unblock_threads() G_STMT_START { \ + if (_PyGObject_API->unblock_threads != NULL) \ + (* _PyGObject_API->unblock_threads)(); \ + } G_STMT_END + #define init_pygobject() { \ PyObject *gobject = PyImport_ImportModule("gobject"); \ |