[pygobject] Store the closure cache in the arg cache. Fixes #103
- From: Christoph Reiter <creiter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Store the closure cache in the arg cache. Fixes #103
- Date: Thu, 22 Mar 2018 19:25:42 +0000 (UTC)
commit 5ee92fd95cded121e1f60d7b35ee201c063c56a0
Author: Christoph Reiter <reiter christoph gmail com>
Date: Thu Mar 22 20:06:47 2018 +0100
Store the closure cache in the arg cache. Fixes #103
Instead of creating the closure cache on every call store
it in the arg cache.
The only potential problem here is that the arg cache owns the
closure cache and needs to stay around. But afaics the cache
stays around until interpreter shutdown and the closure
code guards against that and will simply do nothing then.
This would all be easier if the caches were refcounted.
gi/gimodule.c | 4 +++-
gi/pygi-closure.c | 24 +++++++++++++++---------
gi/pygi-closure.h | 1 +
3 files changed, 19 insertions(+), 10 deletions(-)
---
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 136f74dd..dcdc89dd 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -1752,6 +1752,7 @@ _wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args)
GIFieldInfo *field_info = NULL;
gpointer *method_ptr = NULL;
PyGICClosure *closure = NULL;
+ PyGIClosureCache *cache = NULL;
if (!PyArg_ParseTuple (args, "O!O!O:hook_up_vfunc_implementation",
&PyGIBaseInfo_Type, &py_info,
@@ -1778,7 +1779,8 @@ _wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args)
offset = g_field_info_get_offset (field_info);
method_ptr = G_STRUCT_MEMBER_P (implementor_vtable, offset);
- closure = _pygi_make_native_closure ( (GICallableInfo*) callback_info,
+ cache = pygi_closure_cache_new (callback_info);
+ closure = _pygi_make_native_closure ( (GICallableInfo*) callback_info, cache,
GI_SCOPE_TYPE_NOTIFIED, py_function, NULL);
*method_ptr = closure->closure;
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index b764ab8f..b219971f 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -33,6 +33,7 @@ typedef struct _PyGICallbackCache
gssize destroy_notify_index;
GIScopeType scope;
GIInterfaceInfo *interface_info;
+ PyGIClosureCache *closure_cache;
} PyGICallbackCache;
/* This maintains a list of closures which can be free'd whenever
@@ -566,12 +567,8 @@ _pygi_closure_handle (ffi_cif *cif,
may be executing python code */
py_state = PyGILState_Ensure ();
- if (closure->cache == NULL) {
- closure->cache = pygi_closure_cache_new ((GICallableInfo *) closure->info);
-
- if (closure->cache == NULL)
- goto end;
- }
+ if (closure->cache == NULL)
+ goto end;
state.user_data = closure->user_data;
@@ -641,8 +638,7 @@ void _pygi_invoke_closure_free (gpointer data)
if (invoke_closure->info)
g_base_info_unref ( (GIBaseInfo*) invoke_closure->info);
- if (invoke_closure->cache != NULL)
- pygi_callable_cache_free ((PyGICallableCache *) invoke_closure->cache);
+ invoke_closure->cache = NULL;
_pygi_invoke_closure_clear_py_data(invoke_closure);
@@ -652,6 +648,7 @@ void _pygi_invoke_closure_free (gpointer data)
PyGICClosure*
_pygi_make_native_closure (GICallableInfo* info,
+ PyGIClosureCache *cache,
GIScopeType scope,
PyObject *py_function,
gpointer py_user_data)
@@ -668,6 +665,7 @@ _pygi_make_native_closure (GICallableInfo* info,
closure->info = (GICallableInfo *) g_base_info_ref ( (GIBaseInfo *) info);
closure->function = py_function;
closure->user_data = py_user_data;
+ closure->cache = cache;
Py_INCREF (py_function);
Py_XINCREF (closure->user_data);
@@ -750,7 +748,9 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
callable_info = (GICallableInfo *)callback_cache->interface_info;
- closure = _pygi_make_native_closure (callable_info, callback_cache->scope, py_arg, py_user_data);
+ closure = _pygi_make_native_closure (
+ callable_info, callback_cache->closure_cache, callback_cache->scope,
+ py_arg, py_user_data);
arg->v_pointer = closure->closure;
/* always decref the user data as _pygi_make_native_closure adds its own ref */
@@ -836,6 +836,11 @@ _callback_cache_free_func (PyGICallbackCache *cache)
if (cache->interface_info != NULL)
g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
+ if (cache->closure_cache != NULL) {
+ pygi_callable_cache_free ((PyGICallableCache *) cache->closure_cache);
+ cache->closure_cache = NULL;
+ }
+
g_slice_free (PyGICallbackCache, cache);
}
}
@@ -909,6 +914,7 @@ pygi_arg_callback_setup_from_info (PyGICallbackCache *arg_cache,
arg_cache->interface_info = iface_info;
if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ arg_cache->closure_cache = pygi_closure_cache_new (arg_cache->interface_info);
cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
}
diff --git a/gi/pygi-closure.h b/gi/pygi-closure.h
index c0e84219..30da2cf7 100644
--- a/gi/pygi-closure.h
+++ b/gi/pygi-closure.h
@@ -50,6 +50,7 @@ void _pygi_closure_handle (ffi_cif *cif, void *result, void
void _pygi_invoke_closure_free (gpointer user_data);
PyGICClosure* _pygi_make_native_closure (GICallableInfo* info,
+ PyGIClosureCache *cache,
GIScopeType scope,
PyObject *function,
gpointer user_data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]