[pygobject] Store the closure cache in the arg cache. Fixes #103



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]