[pygobject] cache refactoring: Use GPtrArray for callable arg cache



commit c19bed69c669160737e12d92cc29f3e6d1b008cc
Author: Simon Feltman <sfeltman src gnome org>
Date:   Sun Jul 28 16:44:01 2013 -0700

    cache refactoring: Use GPtrArray for callable arg cache
    
    Replace manual management of the C array holding individual
    argument caches with usage of GPtrArray. This provides storage
    of the array length along with item memory management.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=640812

 gi/pygi-cache.c           |   62 ++++++++++++++++++++++----------------------
 gi/pygi-cache.h           |   16 +++++++++--
 gi/pygi-invoke.c          |   16 ++++++------
 gi/pygi-marshal-cleanup.c |    8 +++---
 gi/pygi-marshal-from-py.c |    6 ++--
 gi/pygi-marshal-to-py.c   |    6 ++--
 6 files changed, 62 insertions(+), 52 deletions(-)
---
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index b3acd61..179dbe7 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -103,23 +103,17 @@ _callback_cache_free_func (PyGICallbackCache *cache)
 void
 _pygi_callable_cache_free (PyGICallableCache *cache)
 {
-    gssize i;
-
     if (cache == NULL)
         return;
 
     g_slist_free (cache->to_py_args);
     g_slist_free (cache->arg_name_list);
     g_hash_table_destroy (cache->arg_name_hash);
+    g_ptr_array_unref (cache->args_cache);
 
-    for (i = 0; i < cache->n_args; i++) {
-        PyGIArgCache *tmp = cache->args_cache[i];
-        _pygi_arg_cache_free (tmp);
-    }
     if (cache->return_cache != NULL)
         _pygi_arg_cache_free (cache->return_cache);
 
-    g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
     g_slice_free (PyGICallableCache, cache);
 }
 
@@ -314,7 +308,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
 
     if (seq_cache->len_arg_index >= 0) {
         PyGIArgCache *child_cache = 
-            callable_cache->args_cache[seq_cache->len_arg_index];
+            _pygi_callable_cache_get_arg (callable_cache, seq_cache->len_arg_index);
 
         if (child_cache == NULL) {
             child_cache = _arg_cache_alloc ();
@@ -333,7 +327,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
         child_cache->to_py_marshaller = NULL;
         child_cache->from_py_marshaller = NULL;
 
-        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
+        _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
     }
 
     arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
@@ -356,7 +350,8 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
     seq_cache->array_type = g_type_info_get_array_type (type_info);
 
     if (seq_cache->len_arg_index >= 0) {
-        PyGIArgCache *child_cache = callable_cache->args_cache[seq_cache->len_arg_index];
+        PyGIArgCache *child_cache = _pygi_callable_cache_get_arg (callable_cache,
+                                                                  seq_cache->len_arg_index);
         if (seq_cache->len_arg_index < arg_index)
              callable_cache->n_to_py_child_args++;
 
@@ -376,7 +371,7 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
         child_cache->to_py_marshaller = NULL;
         child_cache->from_py_marshaller = NULL;
 
-        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
+        _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
     }
 
     return TRUE;
@@ -509,14 +504,16 @@ _arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
         PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
         user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
         user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
-        callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
+        _pygi_callable_cache_set_arg (callable_cache, callback_cache->user_data_index,
+                                      user_data_arg_cache);
     }
 
     if (callback_cache->destroy_notify_index >= 0) {
         PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
         destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
         destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
-        callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
+        _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index,
+                                      destroy_arg_cache);
     }
     arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
     arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
@@ -780,19 +777,19 @@ _arg_cache_new (GITypeInfo *type_info,
                 * need to update indexes if this happens
                 */ 
                if (seq_cache->len_arg_index > -1 &&
-                   callable_cache->args_cache[seq_cache->len_arg_index]->meta_type == 
PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
+                   _pygi_callable_cache_get_arg (callable_cache,
+                                                 seq_cache->len_arg_index)->meta_type == 
PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
                    gssize i;
-                   PyGIArgCache *child_cache =
-                       callable_cache->args_cache[seq_cache->len_arg_index];
-
+                   PyGIArgCache *child_cache = _pygi_callable_cache_get_arg (callable_cache,
+                                                                             seq_cache->len_arg_index);
                    child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
                    py_arg_index -= 1;
                    callable_cache->n_py_args -= 1;
 
                    for (i = seq_cache->len_arg_index + 1; 
-                          i < callable_cache->n_args; 
+                          i < _pygi_callable_cache_args_len (callable_cache);
                             i++) {
-                       PyGIArgCache *update_cache = callable_cache->args_cache[i];
+                       PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
                        if (update_cache == NULL)
                            break;
 
@@ -914,10 +911,10 @@ _arg_name_list_generate (PyGICallableCache *callable_cache)
         g_hash_table_remove_all (callable_cache->arg_name_hash);
     }
 
-    for (i=0; i < callable_cache->n_args; i++) {
+    for (i=0; i < _pygi_callable_cache_args_len (callable_cache); i++) {
         PyGIArgCache *arg_cache = NULL;
 
-        arg_cache = callable_cache->args_cache[i];
+        arg_cache = _pygi_callable_cache_get_arg (callable_cache, i);
 
         if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
             arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
@@ -1016,7 +1013,7 @@ _args_cache_generate (GICallableInfo *callable_info,
         if (instance_cache == NULL)
             return FALSE;
 
-        callable_cache->args_cache[arg_index] = instance_cache;
+        _pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
 
         arg_index++;
         callable_cache->n_from_py_args++;
@@ -1024,7 +1021,7 @@ _args_cache_generate (GICallableInfo *callable_info,
     }
 
 
-    for (i=0; arg_index < callable_cache->n_args; arg_index++, i++) {
+    for (i=0; arg_index < _pygi_callable_cache_args_len (callable_cache); arg_index++, i++) {
         PyGIArgCache *arg_cache = NULL;
         GIArgInfo *arg_info;
         GITypeInfo *type_info;
@@ -1039,7 +1036,7 @@ _args_cache_generate (GICallableInfo *callable_info,
         if (g_arg_info_get_closure (arg_info) == i) {
 
             arg_cache = _arg_cache_alloc ();
-            callable_cache->args_cache[arg_index] = arg_cache;
+            _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
 
             arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
             arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
@@ -1066,8 +1063,8 @@ _args_cache_generate (GICallableInfo *callable_info,
          * and continue
          * fill in it's c_arg_index, add to the in count
          */
-        if (callable_cache->args_cache[arg_index] != NULL) {
-            arg_cache = callable_cache->args_cache[arg_index];
+        arg_cache = _pygi_callable_cache_get_arg (callable_cache, arg_index);
+        if (arg_cache != NULL) {
             if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) {
                 arg_cache->py_arg_index = callable_cache->n_py_args;
                 callable_cache->n_py_args++;
@@ -1122,7 +1119,7 @@ _args_cache_generate (GICallableInfo *callable_info,
                 g_slist_append (callable_cache->to_py_args, arg_cache);
         }
 
-        callable_cache->args_cache[arg_index] = arg_cache;
+        _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
         g_base_info_unref( (GIBaseInfo *)type_info);
         g_base_info_unref( (GIBaseInfo *)arg_info);
 
@@ -1141,6 +1138,7 @@ arg_err:
 PyGICallableCache *
 _pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
 {
+    gint n_args;
     PyGICallableCache *cache;
     GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
 
@@ -1185,15 +1183,17 @@ _pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
         cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
     }
 
-    cache->n_args = g_callable_info_get_n_args (callable_info);
+    n_args = g_callable_info_get_n_args (callable_info);
 
     /* if we are a method or vfunc make sure the instance parameter is counted */
     if (cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
             cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)
-        cache->n_args++;
+        n_args++;
 
-    if (cache->n_args > 0)
-        cache->args_cache = g_slice_alloc0 (cache->n_args * sizeof (PyGIArgCache *));
+    if (n_args >= 0) {
+        cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) _pygi_arg_cache_free);
+        g_ptr_array_set_size (cache->args_cache, n_args);
+    }
 
     if (!_args_cache_generate (callable_info, cache))
         goto err;
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 25c6db6..94c8fdf 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -172,7 +172,7 @@ struct _PyGICallableCache
     PyGIFunctionType function_type;
 
     PyGIArgCache *return_cache;
-    PyGIArgCache **args_cache;
+    GPtrArray *args_cache;
     GSList *to_py_args;
     GSList *arg_name_list; /* for keyword arg matching */
     GHashTable *arg_name_hash;
@@ -191,8 +191,6 @@ struct _PyGICallableCache
      */
     gssize n_to_py_child_args;
 
-    gssize n_args;
-
     /* Number of Python arguments expected for invoking the gi function. */
     gssize n_py_args;
 };
@@ -203,6 +201,18 @@ void _pygi_callable_cache_free     (PyGICallableCache *cache);
 PyGICallableCache *_pygi_callable_cache_new (GICallableInfo *callable_info,
                                              gboolean is_ccallback);
 
+#define _pygi_callable_cache_args_len(cache) ((cache)->args_cache)->len
+
+inline static PyGIArgCache *
+_pygi_callable_cache_get_arg (PyGICallableCache *cache, guint index) {
+    return (PyGIArgCache *) g_ptr_array_index (cache->args_cache, index);
+}
+
+inline static void
+_pygi_callable_cache_set_arg (PyGICallableCache *cache, guint index, PyGIArgCache *arg_cache) {
+    cache->args_cache->pdata[index] = arg_cache;
+}
+
 G_END_DECLS
 
 #endif /* __PYGI_CACHE_H__ */
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 17cd278..7abd9e6 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -299,14 +299,14 @@ _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
     }
     state->n_py_in_args = PyTuple_Size (state->py_in_args);
 
-    state->args = g_slice_alloc0 (cache->n_args * sizeof (GIArgument *));
-    if (state->args == NULL && cache->n_args != 0) {
+    state->args = g_slice_alloc0 (_pygi_callable_cache_args_len (cache) * sizeof (GIArgument *));
+    if (state->args == NULL && _pygi_callable_cache_args_len (cache) != 0) {
         PyErr_NoMemory();
         return FALSE;
     }
 
-    state->args_data = g_slice_alloc0 (cache->n_args * sizeof (gpointer));
-    if (state->args_data == NULL && cache->n_args != 0) {
+    state->args_data = g_slice_alloc0 (_pygi_callable_cache_args_len (cache) * sizeof (gpointer));
+    if (state->args_data == NULL && _pygi_callable_cache_args_len (cache) != 0) {
         PyErr_NoMemory();
         return FALSE;
     }
@@ -337,8 +337,8 @@ _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
 static inline void
 _invoke_state_clear (PyGIInvokeState *state, PyGICallableCache *cache)
 {
-    g_slice_free1 (cache->n_args * sizeof(GIArgument *), state->args);
-    g_slice_free1 (cache->n_args * sizeof(gpointer), state->args_data);
+    g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(GIArgument *), state->args);
+    g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(gpointer), state->args_data);
     g_slice_free1 (cache->n_from_py_args * sizeof(GIArgument), state->in_args);
     g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_args);
     g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_values);
@@ -408,9 +408,9 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
         return FALSE;
     }
 
-    for (i = 0; i < cache->n_args; i++) {
+    for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
         GIArgument *c_arg;
-        PyGIArgCache *arg_cache = cache->args_cache[i];
+        PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i);
         PyObject *py_arg = NULL;
 
         switch (arg_cache->direction) {
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index d7d1b63..57ded65 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -93,8 +93,8 @@ pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState   *state,
     gssize i;
 
     /* For in success, call cleanup for all GI_DIRECTION_IN values only. */
-    for (i = 0; i < cache->n_args; i++) {
-        PyGIArgCache *arg_cache = cache->args_cache[i];
+    for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
+        PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
         PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
 
         if (cleanup_func &&
@@ -157,8 +157,8 @@ pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState   *state,
 
     state->failed = TRUE;
 
-    for (i = 0; i < cache->n_args  && i <= failed_arg_index; i++) {
-        PyGIArgCache *arg_cache = cache->args_cache[i];
+    for (i = 0; i < _pygi_callable_cache_args_len (cache)  && i <= failed_arg_index; i++) {
+        PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
         PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
         gpointer data = state->args[i]->v_pointer;
 
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index 52c91d9..92f965f 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -887,7 +887,7 @@ array_success:
     if (sequence_cache->len_arg_index >= 0) {
         /* we have an child arg to handle */
         PyGIArgCache *child_cache =
-            callable_cache->args_cache[sequence_cache->len_arg_index];
+            _pygi_callable_cache_get_arg (callable_cache, sequence_cache->len_arg_index);
 
         if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) {
             gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer;
@@ -1249,7 +1249,7 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState   *state,
     callback_cache = (PyGICallbackCache *)arg_cache;
 
     if (callback_cache->user_data_index > 0) {
-        user_data_cache = callable_cache->args_cache[callback_cache->user_data_index];
+        user_data_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->user_data_index);
         if (user_data_cache->py_arg_index < state->n_py_in_args) {
             /* py_user_data is a borrowed reference. */
             py_user_data = PyTuple_GetItem (state->py_in_args, user_data_cache->py_arg_index);
@@ -1297,7 +1297,7 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState   *state,
      * later on in _pygi_destroy_notify_callback_closure.
      */
     if (callback_cache->destroy_notify_index > 0) {
-        destroy_cache = callable_cache->args_cache[callback_cache->destroy_notify_index];
+        destroy_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->destroy_notify_index);
     }
 
     if (destroy_cache) {
diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c
index d59e1e3..c9fbce9 100644
--- a/gi/pygi-marshal-to-py.c
+++ b/gi/pygi-marshal-to-py.c
@@ -296,10 +296,10 @@ _pygi_marshal_to_py_array (PyGIInvokeState   *state,
             }
         } else {
             GIArgument *len_arg = state->args[seq_cache->len_arg_index];
+            PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache,
+                                                                    seq_cache->len_arg_index);
 
-            if (!gi_argument_to_gsize (len_arg,
-                                       &len,
-                                       callable_cache->args_cache[seq_cache->len_arg_index]->type_tag)) {
+            if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) {
                 return NULL;
             }
         }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]