diff options
author | James Henstridge <james@daa.com.au> | 2002-01-07 10:46:32 +0000 |
---|---|---|
committer | James Henstridge <jamesh@src.gnome.org> | 2002-01-07 10:46:32 +0000 |
commit | 1bc78a422c4127c3d18cf21d1f28a16469d215b9 (patch) | |
tree | 3090f188ed51906be9532d6ce19a4b6ab73d6fe9 | |
parent | 22ddb79502701fc47318ae05e3a7f5e085b9fa68 (diff) | |
download | pygtk-1bc78a422c4127c3d18cf21d1f28a16469d215b9.tar.gz |
add overriden implementation that allows threads while waiting, so some
2002-01-07 James Henstridge <james@daa.com.au>
* gtk/gdk.override (_wrap_gdk_threads_enter): add overriden
implementation that allows threads while waiting, so some other
thread has a chance to give up the gdk lock.
* gtk/gtkmodule.c (functions): remove stuff.
* gtk/pygtk-private.h: remove definitions here as well.
* gtk/pygtk.h (_PyGtk_FunctionStruct): remove destroy notify and
thread block stuff.
* gtk/gtkobject-support.c: remove pygtk_destroy_notify.
* gtk/gtk.override (pygtk_tree_foreach_marshal): move this
function here from gtkobject-support.c, and don't bother blocking
threads.
(_wrap_gtk_tree_selection_selected_foreach): same here -- don't
need to unblock threads.
(pygtk_tree_selection_marshal): move this function here from
gtkobject-support.c. Convert to use pyg_block_threads.
(_wrap_gtk_dialog_run): add overriden implementation that unblocks
threads.
(_wrap_gtk_main): use pyg_block_threads
(_wrap_gtk_main_iteration): same.
(_wrap_gtk_item_factory_create_items): same here.
(_wrap_gtk_menu_popup): same here.
(_wrap_gtk_clist_set_row_data): use pyg_destroy_notify
(_wrap_gtk_timeout_add): same here.
(_wrap_gtk_idle_add): same here.
(_wrap_gtk_quit_add): same here.
(_wrap_gtk_input_add_full): same here.
(_wrap_gtk_ctree_node_set_row_data): same here.
* gtk/gtkobject-support.c: remove PyGTK_BLOCK_THREADS and
PyGTK_UNBLOCK_THREADS macros.
(pygtk_destroy_notify): use pyg_block_threads.
(pygtk_custom_destroy_notify): same.
(pygtk_handler_marshal): same.
(pygtk_input_marshal): same.
* gtk/gdk.override (_wrap_gdk_threads_init): register gdk lock
based recursive threads block/unblock functions. If threading was
disabled at compile time, then this function will error out.
* gtk/gdk.defs (threads_enter, threads_leave, threads_leave): add
functions.
* gobjectmodule.c (functions): add destroy_notify here as well.
* pygobject.h: add destroy_notify to the PyGObject_Functions
vtable.
-rw-r--r-- | ChangeLog | 52 | ||||
-rw-r--r-- | gobject/gobjectmodule.c | 9 | ||||
-rw-r--r-- | gobject/pygobject.h | 3 | ||||
-rw-r--r-- | gobjectmodule.c | 9 | ||||
-rw-r--r-- | gtk/gdk.defs | 16 | ||||
-rw-r--r-- | gtk/gdk.override | 97 | ||||
-rw-r--r-- | gtk/gtk.override | 110 | ||||
-rw-r--r-- | gtk/gtkmodule.c | 7 | ||||
-rw-r--r-- | gtk/gtkobject-support.c | 151 | ||||
-rw-r--r-- | gtk/pygtk-private.h | 16 | ||||
-rw-r--r-- | gtk/pygtk.h | 11 | ||||
-rw-r--r-- | pygobject.h | 3 |
12 files changed, 283 insertions, 201 deletions
@@ -1,5 +1,57 @@ 2002-01-07 James Henstridge <james@daa.com.au> + * gtk/gdk.override (_wrap_gdk_threads_enter): add overriden + implementation that allows threads while waiting, so some other + thread has a chance to give up the gdk lock. + + * gtk/gtkmodule.c (functions): remove stuff. + + * gtk/pygtk-private.h: remove definitions here as well. + + * gtk/pygtk.h (_PyGtk_FunctionStruct): remove destroy notify and + thread block stuff. + + * gtk/gtkobject-support.c: remove pygtk_destroy_notify. + + * gtk/gtk.override (pygtk_tree_foreach_marshal): move this + function here from gtkobject-support.c, and don't bother blocking + threads. + (_wrap_gtk_tree_selection_selected_foreach): same here -- don't + need to unblock threads. + (pygtk_tree_selection_marshal): move this function here from + gtkobject-support.c. Convert to use pyg_block_threads. + (_wrap_gtk_dialog_run): add overriden implementation that unblocks + threads. + (_wrap_gtk_main): use pyg_block_threads + (_wrap_gtk_main_iteration): same. + (_wrap_gtk_item_factory_create_items): same here. + (_wrap_gtk_menu_popup): same here. + (_wrap_gtk_clist_set_row_data): use pyg_destroy_notify + (_wrap_gtk_timeout_add): same here. + (_wrap_gtk_idle_add): same here. + (_wrap_gtk_quit_add): same here. + (_wrap_gtk_input_add_full): same here. + (_wrap_gtk_ctree_node_set_row_data): same here. + + * gtk/gtkobject-support.c: remove PyGTK_BLOCK_THREADS and + PyGTK_UNBLOCK_THREADS macros. + (pygtk_destroy_notify): use pyg_block_threads. + (pygtk_custom_destroy_notify): same. + (pygtk_handler_marshal): same. + (pygtk_input_marshal): same. + + * gtk/gdk.override (_wrap_gdk_threads_init): register gdk lock + based recursive threads block/unblock functions. If threading was + disabled at compile time, then this function will error out. + + * gtk/gdk.defs (threads_enter, threads_leave, threads_leave): add + functions. + + * gobjectmodule.c (functions): add destroy_notify here as well. + + * pygobject.h: add destroy_notify to the PyGObject_Functions + vtable. + * gobjectmodule.c (pyg_set_thread_block_funcs): handler for registering thread block/unblock funcs. (pygobject_destroy_notify): block threads during DECREF call. diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index 1e61fd2b..39fba99f 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -250,7 +250,7 @@ pyg_param_spec_new(GParamSpec *pspec) /* -------------- class <-> wrapper manipulation --------------- */ static void -pygobject_destroy_notify(gpointer user_data) +pyg_destroy_notify(gpointer user_data) { PyObject *obj = (PyObject *)user_data; @@ -1228,7 +1228,7 @@ pygobject_dealloc(PyGObject *self) Py_INCREF(self); /* grab a reference on the wrapper */ self->hasref = TRUE; g_object_set_qdata_full(obj, pygobject_ownedref_key, - self, pygobject_destroy_notify); + self, pyg_destroy_notify); g_object_unref(obj); /* we ref the type, so subtype_dealloc() doesn't kill off our @@ -1441,7 +1441,7 @@ pygobject_set_data(PyGObject *self, PyObject *args) return NULL; quark = g_quark_from_string(key); Py_INCREF(data); - g_object_set_qdata_full(self->obj, quark, data, pygobject_destroy_notify); + g_object_set_qdata_full(self->obj, quark, data, pyg_destroy_notify); Py_INCREF(Py_None); return Py_None; } @@ -3002,7 +3002,10 @@ static struct _PyGObject_Functions functions = { pygobject_register_wrapper, pygobject_lookup_class, pygobject_new, + pyg_closure_new, + pyg_destroy_notify, + pyg_type_from_object, pyg_type_wrapper_new, pyg_enum_get_value, diff --git a/gobject/pygobject.h b/gobject/pygobject.h index 8fa45424..9918dd30 100644 --- a/gobject/pygobject.h +++ b/gobject/pygobject.h @@ -37,8 +37,10 @@ struct _PyGObject_Functions { void (* register_wrapper)(PyObject *self); PyTypeObject *(* lookup_class)(GType type); PyObject *(* newgobj)(GObject *obj); + GClosure *(* closure_new)(PyObject *callback, PyObject *extra_args, PyObject *swap_data); + GDestroyNotify destroy_notify; GType (* type_from_object)(PyObject *obj); PyObject *(* type_wrapper_new)(GType type); @@ -91,6 +93,7 @@ struct _PyGObject_Functions *_PyGObject_API; #define pygobject_lookup_class (_PyGObject_API->lookup_class) #define pygobject_new (_PyGObject_API->newgobj) #define pyg_closure_new (_PyGObject_API->closure_new) +#define pyg_destroy_notify (_PyGObject_API->destroy_notify) #define pyg_type_from_object (_PyGObject_API->type_from_object) #define pyg_type_wrapper_new (_PyGObject_API->type_wrapper_new) #define pyg_enum_get_value (_PyGObject_API->enum_get_value) diff --git a/gobjectmodule.c b/gobjectmodule.c index 1e61fd2b..39fba99f 100644 --- a/gobjectmodule.c +++ b/gobjectmodule.c @@ -250,7 +250,7 @@ pyg_param_spec_new(GParamSpec *pspec) /* -------------- class <-> wrapper manipulation --------------- */ static void -pygobject_destroy_notify(gpointer user_data) +pyg_destroy_notify(gpointer user_data) { PyObject *obj = (PyObject *)user_data; @@ -1228,7 +1228,7 @@ pygobject_dealloc(PyGObject *self) Py_INCREF(self); /* grab a reference on the wrapper */ self->hasref = TRUE; g_object_set_qdata_full(obj, pygobject_ownedref_key, - self, pygobject_destroy_notify); + self, pyg_destroy_notify); g_object_unref(obj); /* we ref the type, so subtype_dealloc() doesn't kill off our @@ -1441,7 +1441,7 @@ pygobject_set_data(PyGObject *self, PyObject *args) return NULL; quark = g_quark_from_string(key); Py_INCREF(data); - g_object_set_qdata_full(self->obj, quark, data, pygobject_destroy_notify); + g_object_set_qdata_full(self->obj, quark, data, pyg_destroy_notify); Py_INCREF(Py_None); return Py_None; } @@ -3002,7 +3002,10 @@ static struct _PyGObject_Functions functions = { pygobject_register_wrapper, pygobject_lookup_class, pygobject_new, + pyg_closure_new, + pyg_destroy_notify, + pyg_type_from_object, pyg_type_wrapper_new, pyg_enum_get_value, diff --git a/gtk/gdk.defs b/gtk/gdk.defs index 8a01cf6e..c9628226 100644 --- a/gtk/gdk.defs +++ b/gtk/gdk.defs @@ -42,6 +42,22 @@ ) ) +(define-function threads_enter + (c-name "gdk_threads_enter") + (return-type "none") +) + +(define-function threads_leave + (c-name "gdk_threads_leave") + (return-type "none") +) + +(define-function threads_init + (c-name "gdk_threads_init") + (return-type "none") +) + + ;; From /opt/gtk2/include/gtk-2.0/gdk/gdkcolor.h (define-function gdk_colormap_get_type diff --git a/gtk/gdk.override b/gtk/gdk.override index 7746d056..cc90548f 100644 --- a/gtk/gdk.override +++ b/gtk/gdk.override @@ -1,6 +1,10 @@ /* -*- Mode: C; c-basic-offset: 4 -*- */ %% headers +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + #define NO_IMPORT_PYGOBJECT #include "pygobject.h" #include <gtk/gtk.h> @@ -18,6 +22,99 @@ import pango.Layout as PyPangoLayout_Type ignore-glob *_get_type %% +override gdk_threads_init noargs + +/* block/unblock threads implementations using GDK lock to handle + * recursion (as in 1.2 version). Here is the comments about it from + * the 1.2 version of pygtk:*/ + +/* The threading hacks are based on ones supplied by Duncan Grisby + * 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 ENABLE_PYGTK_THREADING +static GStaticPrivate pythreadstate_key = G_STATIC_PRIVATE_INIT; +static GStaticPrivate counter_key = G_STATIC_PRIVATE_INIT; +#define INITIAL_LOCK_COUNT 1 + +static void +pygdk_block_threads (void) +{ + gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key)); + g_assert(functions.block_threads == pyg_block_threads); + if (counter == INITIAL_LOCK_COUNT) { + PyThreadState *_save; + _save = g_static_private_get(&pythreadstate_key); + if(functions.gdk_threads_leave) + functions.gdk_threads_leave(); + Py_BLOCK_THREADS; + } + counter--; + g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL); +} +static void +pyg_unblock_threads (void) +{ + gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key)); + g_assert(functions.unblock_threads == pyg_unblock_threads); + counter++; + if (counter == INITIAL_LOCK_COUNT) { + PyThreadState *_save; + Py_UNBLOCK_THREADS; + if(functions.gdk_threads_enter) + functions.gdk_threads_enter(); + g_static_private_set(&pythreadstate_key, _save, NULL); + } + g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL); +} +#endif + +static PyObject * +_wrap_gdk_threads_init(PyObject *self) +{ +#ifdef ENABLE_PYGTK_THREADING + /* register gdk thread block/unblock routines with gobjectmodule */ + pyg_set_thread_block_funcs (pygdk_block_threads, pygdk_unblock_threads); + + gdk_threads_init(); + + Py_INCREF(Py_None); + return Py_None; +#else + PyErr_SetString(PyExc_RuntimeError, + "pygtk threading disabled at compile time"); + return NULL; +#endif +} +%% +override gdk_threads_enter noargs +static PyObject * +_wrap_gdk_threads_enter(PyObject *self) +{ + /* must allow threads while acquiring lock, or no other python + * code will execute while we wait! */ + Py_BEGIN_ALLOW_THREADS; + gdk_threads_enter(); + Py_END_ALLOW_THREADS; + + Py_INCREF(Py_None); + return Py_None; +} +%% override gdk_draw_polygon kwargs static PyObject * _wrap_gdk_draw_polygon(PyGObject *self, PyObject *args, PyObject *kwargs) diff --git a/gtk/gtk.override b/gtk/gtk.override index 1599184b..eb2a0511 100644 --- a/gtk/gtk.override +++ b/gtk/gtk.override @@ -675,7 +675,7 @@ _wrap_gtk_clist_set_row_data(PyGObject *self, PyObject *args, return NULL; Py_INCREF(data); gtk_clist_set_row_data_full(GTK_CLIST(self->obj), row, data, - (GtkDestroyNotify)pygtk_destroy_notify); + (GtkDestroyNotify)pyg_destroy_notify); Py_INCREF(Py_None); return Py_None; } @@ -1518,6 +1518,26 @@ _wrap_gtk_tree_selection_get_selected(PyGObject *self) } %% override gtk_tree_selection_selected_foreach +static void +pygtk_tree_foreach_marshal(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + PyGtkCustomNotify *cunote = data; + PyObject *pypath, *retobj; + + g_assert(cunote->func); + + pypath = pygtk_tree_path_to_pyobject(path); + if (cunote->data) + retobj = PyEval_CallFunction(cunote->func, "(OO)", pypath, + cunote->data); + else + retobj = PyEval_CallFunction(cunote->func, "(O)", pypath); + Py_DECREF(pypath); + Py_XDECREF(retobj); +} static PyObject * _wrap_gtk_tree_selection_selected_foreach(PyGObject *self, PyObject *args) { @@ -1530,16 +1550,53 @@ _wrap_gtk_tree_selection_selected_foreach(PyGObject *self, PyObject *args) cunote.func = pyfunc; cunote.data = pyarg; - pygtk_unblock_threads(); gtk_tree_selection_selected_foreach(GTK_TREE_SELECTION(self->obj), pygtk_tree_foreach_marshal, &cunote); - pygtk_block_threads(); Py_INCREF(Py_None); return Py_None; } %% override gtk_tree_selection_set_select_function + +static gboolean +pygtk_tree_selection_marshal(GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer data) +{ + gboolean retval = FALSE; + PyGtkCustomNotify *cunote = data; + PyObject *pypath, *retobj; + + pyg_block_threads(); + + g_assert(cunote->func); + + pypath = pygtk_tree_path_to_pyobject(path); + if (cunote->data) + retobj = PyEval_CallFunction(cunote->func, "(OO)", pypath, + cunote->data); + else + retobj = PyEval_CallFunction(cunote->func, "(O)", pypath); + Py_DECREF(pypath); + if (retobj) { + if(retobj == Py_None); + else if(PyInt_Check(retobj)) + retval = PyInt_AsLong(retobj) && TRUE; + else if(PyLong_Check(retobj)) + retval = PyLong_AsLongLong(retobj) && TRUE; + else if(PyString_Check(retobj)) + retval = PyString_GET_SIZE(retobj) && TRUE; + + Py_DECREF(retobj); + } + + pyg_unblock_threads(); + + return retval; +} static PyObject * _wrap_gtk_tree_selection_set_select_function(PyGObject *self, PyObject *args) { @@ -1551,8 +1608,10 @@ _wrap_gtk_tree_selection_set_select_function(PyGObject *self, PyObject *args) return NULL; cunote = g_new0(PyGtkCustomNotify, 1); - Py_XINCREF(cunote->func = pyfunc); - Py_XINCREF(cunote->data = pyarg); + cunote->func = pyfunc; + cunote->data = pyarg; + Py_INCREF(cunote->func); + Py_XINCREF(cunote->data); gtk_tree_selection_set_select_function(GTK_TREE_SELECTION(self->obj), pygtk_tree_selection_marshal, cunote, @@ -1850,9 +1909,9 @@ override gtk_main noargs static PyObject * _wrap_gtk_main(PyObject *self) { - pygtk_unblock_threads(); + pyg_unblock_threads(); gtk_main(); - pygtk_block_threads(); + pyg_block_threads(); if (PyErr_Occurred()) return NULL; Py_INCREF(Py_None); @@ -1869,9 +1928,9 @@ _wrap_gtk_main_iteration(PyObject *self, PyObject *args, PyObject *kwargs) if(!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:main_iteration", kwlist, &block)) return NULL; - pygtk_unblock_threads(); + pyg_unblock_threads(); ret = gtk_main_iteration_do(block); - pygtk_block_threads(); + pyg_block_threads(); return PyInt_FromLong(ret); } %% @@ -1907,8 +1966,8 @@ _wrap_gtk_timeout_add(PyObject *self, PyObject *args) if (data == NULL) return NULL; return PyInt_FromLong(gtk_timeout_add_full(interval, NULL, - (GtkCallbackMarshal)pygtk_handler_marshal, - data, (GtkDestroyNotify)pygtk_destroy_notify)); + (GtkCallbackMarshal)pygtk_handler_marshal, + data, (GtkDestroyNotify)pyg_destroy_notify)); } %% override gtk_idle_add @@ -1943,7 +2002,7 @@ _wrap_gtk_idle_add(PyObject *self, PyObject *args) return NULL; return PyInt_FromLong(gtk_idle_add_full(GTK_PRIORITY_DEFAULT, NULL, (GtkCallbackMarshal)pygtk_handler_marshal, - data, (GtkDestroyNotify)pygtk_destroy_notify)); + data, (GtkDestroyNotify)pyg_destroy_notify)); } %% override gtk_quit_add @@ -1979,7 +2038,7 @@ _wrap_gtk_quit_add(PyObject *self, PyObject *args) return NULL; return PyInt_FromLong(gtk_quit_add_full(main_level, NULL, (GtkCallbackMarshal)pygtk_handler_marshal, - data, (GtkDestroyNotify)pygtk_destroy_notify)); + data, (GtkDestroyNotify)pyg_destroy_notify)); } %% override gtk_input_add_full kwargs @@ -2007,7 +2066,7 @@ _wrap_gtk_input_add_full(PyObject *self, PyObject *args, PyObject *kwargs) Py_INCREF(callback); return PyInt_FromLong(gtk_input_add_full(source, condition, NULL, (GtkCallbackMarshal)pygtk_input_marshal, callback, - (GtkDestroyNotify)pygtk_destroy_notify)); + (GtkDestroyNotify)pyg_destroy_notify)); } %% override gtk_editable_insert_text kwargs @@ -2033,7 +2092,7 @@ pygtk_item_factory_cb(PyObject *callback, guint action, GtkWidget *widget) { PyObject *ret; - pygtk_block_threads(); + pyg_block_threads(); ret = PyObject_CallFunction(callback, "iO", action, pygobject_new((GObject *)widget)); if (ret == NULL) { @@ -2041,7 +2100,7 @@ pygtk_item_factory_cb(PyObject *callback, guint action, GtkWidget *widget) PyErr_Clear(); } else Py_DECREF(ret); - pygtk_unblock_threads(); + pyg_unblock_threads(); } static PyObject * _wrap_gtk_item_factory_create_items(PyGObject *self, PyObject *args, @@ -2109,7 +2168,7 @@ pygtk_menu_position(GtkMenu *menu, int *x, int *y, PyObject *func) { PyObject *ret; - pygtk_block_threads(); + pyg_block_threads(); ret = PyObject_CallFunction(func, "Oii", pygobject_new((GObject *)menu), *x, *y); if (ret == NULL || !PyArg_ParseTuple(ret, "ii", x, y)) { @@ -2121,7 +2180,7 @@ pygtk_menu_position(GtkMenu *menu, int *x, int *y, PyObject *func) } else { Py_DECREF(ret); } - pygtk_unblock_threads(); + pyg_unblock_threads(); } static PyObject * _wrap_gtk_menu_popup(PyGObject *self, PyObject *args, PyObject *kwargs) @@ -2885,7 +2944,7 @@ _wrap_gtk_ctree_node_set_row_data(PyGObject *self, PyObject *args, Py_INCREF(data); gtk_ctree_node_set_row_data_full(GTK_CTREE(self->obj), pyg_boxed_get(node, GtkCTreeNode), data, - (GtkDestroyNotify)pygtk_destroy_notify); + (GtkDestroyNotify)pyg_destroy_notify); Py_INCREF(Py_None); return Py_None; } @@ -4136,6 +4195,19 @@ _wrap_gtk_dialog_new_with_buttons(PyGObject *self, PyObject *args, return 0; } %% +override gtk_dialog_run noargs +static PyObject * +_wrap_gtk_dialog_run(PyGObject *self) +{ + gint retval; + + pyg_unblock_threads(); + retval = gtk_dialog_run(GTK_DIALOG(self->obj)); + pyg_block_threads(); + + return PyInt_FromLong(retval); +} +%% override gtk_message_dialog_new kwargs static int _wrap_gtk_message_dialog_new(PyGObject *self, PyObject *args, PyObject *kwargs) diff --git a/gtk/gtkmodule.c b/gtk/gtkmodule.c index 96facdf3..cf2aee64 100644 --- a/gtk/gtkmodule.c +++ b/gtk/gtkmodule.c @@ -3,6 +3,7 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif + /* include this first, before NO_IMPORT_PYGOBJECT is defined */ #include <pygobject.h> #include "pygtk-private.h" @@ -18,12 +19,6 @@ extern PyMethodDef pygdk_functions[]; static struct _PyGtk_FunctionStruct functions = { VERSION, - FALSE, - - pygtk_block_threads, - pygtk_unblock_threads, - - pygtk_destroy_notify, &PyGdkAtom_Type, PyGdkAtom_New, }; diff --git a/gtk/gtkobject-support.c b/gtk/gtkobject-support.c index 286d7da6..41571d59 100644 --- a/gtk/gtkobject-support.c +++ b/gtk/gtkobject-support.c @@ -5,89 +5,17 @@ #include "pygtk-private.h" -/* ----------------- Thread stuff -------------------- */ -/* The threading hacks are based on ones supplied by Duncan Grisby - * 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 ENABLE_PYGTK_THREADING -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 -#endif - -void pygtk_block_threads(void) { PyGTK_BLOCK_THREADS } -void pygtk_unblock_threads(void) { PyGTK_UNBLOCK_THREADS } - /* ------------------- object support */ void -pygtk_destroy_notify(gpointer user_data) -{ - PyObject *obj = (PyObject *)user_data; - - PyGTK_BLOCK_THREADS - Py_DECREF(obj); - PyGTK_UNBLOCK_THREADS -} - -void pygtk_custom_destroy_notify(gpointer user_data) { PyGtkCustomNotify *cunote = user_data; - PyGTK_BLOCK_THREADS + pyg_block_threads(); Py_XDECREF(cunote->func); Py_XDECREF(cunote->data); - PyGTK_UNBLOCK_THREADS + pyg_unblock_threads(); g_free(cunote); } @@ -97,7 +25,7 @@ pygtk_handler_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args) { PyObject *ret; - PyGTK_BLOCK_THREADS + pyg_block_threads(); if (PyTuple_Check(func)) ret = PyObject_CallObject(PyTuple_GetItem(func, 0), @@ -108,15 +36,15 @@ pygtk_handler_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args) PyErr_Print(); PyErr_Clear(); *GTK_RETLOC_BOOL(args[0]) = FALSE; - PyGTK_UNBLOCK_THREADS - return; + pyg_unblock_threads(); + return; } if (ret == Py_None || (PyInt_Check(ret) && PyInt_AsLong(ret) == 0)) *GTK_RETLOC_BOOL(args[0]) = FALSE; else *GTK_RETLOC_BOOL(args[0]) = TRUE; Py_DECREF(ret); - PyGTK_UNBLOCK_THREADS + pyg_unblock_threads(); } /* callback for input handlers */ @@ -125,7 +53,7 @@ pygtk_input_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args) { PyObject *tuple, *ret; - PyGTK_BLOCK_THREADS + pyg_block_threads(); tuple = Py_BuildValue("(ii)", GTK_VALUE_INT(args[0]), GTK_VALUE_FLAGS(args[1])); ret = PyObject_CallObject(func, tuple); @@ -135,70 +63,7 @@ pygtk_input_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args) PyErr_Clear(); } else Py_DECREF(ret); - PyGTK_UNBLOCK_THREADS -} - -void -pygtk_tree_foreach_marshal(GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) -{ - PyGtkCustomNotify *cunote = data; - PyObject *pypath, *retobj; - - g_assert(cunote->func); - - PyGTK_BLOCK_THREADS - - pypath = pygtk_tree_path_to_pyobject(path); - if (cunote->data) - retobj = PyEval_CallFunction(cunote->func, "(OO)", pypath, - cunote->data); - else - retobj = PyEval_CallFunction(cunote->func, "(O)", pypath); - Py_DECREF(pypath); - Py_XDECREF(retobj); - - PyGTK_UNBLOCK_THREADS + pyg_unblock_threads(); } -gboolean -pygtk_tree_selection_marshal(GtkTreeSelection *selection, - GtkTreeModel *model, - GtkTreePath *path, - gboolean path_currently_selected, - gpointer data) -{ - gboolean retval = FALSE; - PyGtkCustomNotify *cunote = data; - PyObject *pypath, *retobj; - - g_assert(cunote->func); - - PyGTK_BLOCK_THREADS - - pypath = pygtk_tree_path_to_pyobject(path); - if (cunote->data) - retobj = PyEval_CallFunction(cunote->func, "(OO)", pypath, - cunote->data); - else - retobj = PyEval_CallFunction(cunote->func, "(O)", pypath); - Py_DECREF(pypath); - if (retobj) { - if(retobj == Py_None); - else if(PyInt_Check(retobj)) - retval = PyInt_AsLong(retobj) && TRUE; - else if(PyLong_Check(retobj)) - retval = PyLong_AsLongLong(retobj) && TRUE; - else if(PyString_Check(retobj)) - retval = PyString_GET_SIZE(retobj) && TRUE; - - Py_DECREF(retobj); - } - - PyGTK_UNBLOCK_THREADS - - return retval; -} diff --git a/gtk/pygtk-private.h b/gtk/pygtk-private.h index 12c58c3b..27e6edb8 100644 --- a/gtk/pygtk-private.h +++ b/gtk/pygtk-private.h @@ -22,12 +22,6 @@ extern PyTypeObject PyGdkAtom_Type; /* constructors for PyObject wrappers ... */ PyObject *PyGdkAtom_New(GdkAtom atom); -/* miscelaneous functions */ -void pygtk_block_threads(void); -void pygtk_unblock_threads(void); - -void pygtk_destroy_notify(gpointer data); - void pygtk_handler_marshal(gpointer a, PyObject *func, int nargs,GtkArg *args); void pygtk_input_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args); @@ -43,14 +37,4 @@ typedef struct { void pygtk_custom_destroy_notify(gpointer user_data); -gboolean pygtk_tree_selection_marshal(GtkTreeSelection *selection, - GtkTreeModel *model, - GtkTreePath *path, - gboolean path_currenly_selected, - gpointer data); -void pygtk_tree_foreach_marshal(GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data); - #endif diff --git a/gtk/pygtk.h b/gtk/pygtk.h index 602b7f0a..e34dc174 100644 --- a/gtk/pygtk.h +++ b/gtk/pygtk.h @@ -9,12 +9,6 @@ struct _PyGtk_FunctionStruct { char *pygtkVersion; - gboolean fatalExceptions; - - void (* block_threads)(void); - void (* unblock_threads)(void); - - GtkDestroyNotify destroy_notify; PyTypeObject *gdkAtom_type; PyObject *(* gdkAtom_new)(GdkAtom atom); @@ -52,11 +46,6 @@ struct _PyGtk_FunctionStruct *_PyGtk_API; /* type objects */ #define PyGdkAtom_New (_PyGtk_API->gdkAtom_new) -/* miscelaneous other functions */ -#define pygtk_block_threads (_PyGtk_API->block_threads) -#define pygtk_unblock_threads (_PyGtk_API->unblock_threads) -#define pygtk_destroy_notify (_PyGtk_API->destroy_notify) - /* some variables */ #define PYGTK_VERSION (_PyGtk_API->pygtkVersion) diff --git a/pygobject.h b/pygobject.h index 8fa45424..9918dd30 100644 --- a/pygobject.h +++ b/pygobject.h @@ -37,8 +37,10 @@ struct _PyGObject_Functions { void (* register_wrapper)(PyObject *self); PyTypeObject *(* lookup_class)(GType type); PyObject *(* newgobj)(GObject *obj); + GClosure *(* closure_new)(PyObject *callback, PyObject *extra_args, PyObject *swap_data); + GDestroyNotify destroy_notify; GType (* type_from_object)(PyObject *obj); PyObject *(* type_wrapper_new)(GType type); @@ -91,6 +93,7 @@ struct _PyGObject_Functions *_PyGObject_API; #define pygobject_lookup_class (_PyGObject_API->lookup_class) #define pygobject_new (_PyGObject_API->newgobj) #define pyg_closure_new (_PyGObject_API->closure_new) +#define pyg_destroy_notify (_PyGObject_API->destroy_notify) #define pyg_type_from_object (_PyGObject_API->type_from_object) #define pyg_type_wrapper_new (_PyGObject_API->type_wrapper_new) #define pyg_enum_get_value (_PyGObject_API->enum_get_value) |