[pygobject/invoke-rewrite] [gi-invoke-ng] handle caller allocates cleanup



commit dbe8c4fabc8ac19415a3be0e854d3a54c2317e0b
Author: John (J5) Palmieri <johnp redhat com>
Date:   Fri Apr 29 17:40:13 2011 -0400

    [gi-invoke-ng] handle caller allocates cleanup

 gi/pygi-invoke-ng.c       |    5 +-
 gi/pygi-marshal-cleanup.c |  104 ++++++++++++++++++++++++++++++++++++---------
 gi/pygi-marshal-cleanup.h |    7 ++-
 3 files changed, 90 insertions(+), 26 deletions(-)
---
diff --git a/gi/pygi-invoke-ng.c b/gi/pygi-invoke-ng.c
index 51e6f6e..a1e0ef4 100644
--- a/gi/pygi-invoke-ng.c
+++ b/gi/pygi-invoke-ng.c
@@ -404,13 +404,14 @@ _wrap_g_callable_info_invoke (PyGIBaseInfo *self,
         goto err;
 
     state.stage = PYGI_INVOKE_STAGE_NATIVE_INVOKE_DONE;
-    pygi_marshal_cleanup_args (&state, self->cache);
+    pygi_marshal_cleanup_args (&state, self->cache, FALSE);
 
     ret = _invoke_marshal_out_args (&state, self->cache);
     state.stage = PYGI_INVOKE_STAGE_DONE;
 
 err:
-    pygi_marshal_cleanup_args (&state, self->cache);
+    pygi_marshal_cleanup_args (&state, self->cache,
+                                state.stage != PYGI_INVOKE_STAGE_DONE);
     _invoke_state_clear (&state, self->cache);
     return ret;
 }
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index 56dcccf..f4b58ea 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -21,10 +21,27 @@
  
  #include "pygi-marshal-cleanup.h"
  #include <glib.h>
+static inline void
+_cleanup_caller_allocates (PyGIInvokeState    *state,
+                           PyGIInterfaceCache *cache,
+                           gpointer            data)
+{
+    if (cache->g_type == G_TYPE_BOXED) {
+        gsize size;
+        size = g_struct_info_get_size (cache->interface_info);
+        g_slice_free1 (size, data);
+    } else if (cache->is_foreign) {
+        pygi_struct_foreign_release ((GIBaseInfo *)cache->interface_info,
+                                     data);
+    } else {
+        g_free (data);
+    }
+}
 
-void 
+void
 pygi_marshal_cleanup_args (PyGIInvokeState   *state,
-                           PyGICallableCache *cache)
+                           PyGICallableCache *cache,
+                           gboolean invoke_failure)
 {
     switch (state->stage) {
         case PYGI_INVOKE_STAGE_MARSHAL_IN_IDLE:
@@ -39,29 +56,74 @@ pygi_marshal_cleanup_args (PyGIInvokeState   *state,
             /* we have not yet invoked so we only need to clean up 
                the in args and out caller allocates */
 
-            /* FIXME: handle caller allocates */
             for (i = 0; i < state->current_arg; i++) {
                 PyGIArgCache *arg_cache = cache->args_cache[i];
                 PyGIMarshalCleanupFunc cleanup_func = arg_cache->cleanup;
-                if (cleanup_func != NULL  &&
-                    arg_cache->direction != GI_DIRECTION_OUT) {
+
+                /* FIXME: handle caller allocates */
+                if (invoke_failure && 
+                      arg_cache->direction == GI_DIRECTION_OUT &&
+                        arg_cache->is_caller_allocates) {
+                    _cleanup_caller_allocates (state,
+                                               (PyGIInterfaceCache *) arg_cache,
+                                               state->args[i]->v_pointer);
+                } else if (cleanup_func != NULL  &&
+                             arg_cache->direction != GI_DIRECTION_OUT) {
                     cleanup_func (state, arg_cache, state->args[i]->v_pointer);
                 }
             }
             break;
         }
+
+        case PYGI_INVOKE_STAGE_DONE:
+        case PYGI_INVOKE_STAGE_MARSHAL_RETURN_START:
+            /* clean up the return if not marshalled */
+            if (cache->return_cache != NULL) {
+                PyGIMarshalCleanupFunc cleanup_func =
+                    cache->return_cache->cleanup;
+
+                if (cleanup_func)
+                    cleanup_func (state,
+                                  cache->return_cache,
+                                  state->return_arg.v_pointer);
+            }
+
         case PYGI_INVOKE_STAGE_MARSHAL_OUT_START:
-            /* we have not yet marshalled so decrement to end with previous
-               arg */
-            state->current_arg--;
         case PYGI_INVOKE_STAGE_MARSHAL_OUT_IDLE:
-        case PYGI_INVOKE_STAGE_DONE:
-            /* In args should have already been cleaned up so only cleanup
-               out args */
         case PYGI_INVOKE_STAGE_MARSHAL_RETURN_DONE:
+        {
+            /* Cleanup caller allocate args and any unmarshalled arg */
+            GSList *cache_item = cache->out_args;
+            gsize arg_index = 0;
+
+            if (state->stage == PYGI_INVOKE_STAGE_MARSHAL_OUT_START) {
+                /* we have not yet marshalled so decrement to end with
+                   previous arg */
+                state->current_arg--;
+            }
+
+            /* clean up the args */
+            while (cache_item != NULL) {
+                PyGIArgCache *arg_cache = (PyGIArgCache *) cache_item->data;
+                PyGIMarshalCleanupFunc cleanup_func = arg_cache->cleanup;
+
+                if (arg_index > state->current_arg) {
+                    if (cleanup_func != NULL)
+                        cleanup_func (state,
+                                      arg_cache,
+                                      state->args[arg_cache->c_arg_index]->v_pointer);
+
+                    if (arg_cache->is_caller_allocates)
+                        _cleanup_caller_allocates (state,
+                                                   (PyGIInterfaceCache *) arg_cache,
+                                                   state->args[arg_cache->c_arg_index]->v_pointer);
+                }
+
+                arg_index++;
+                cache_item = cache_item->next;
+            }
             break;
-        case PYGI_INVOKE_STAGE_MARSHAL_RETURN_START:
-            break;
+        }
     }
 }
 
@@ -107,20 +169,20 @@ _pygi_marshal_cleanup_utf8 (PyGIInvokeState *state,
      * we free if transfer == GI_TRANSFER_EVERYTHING
      */
     switch (state->stage) {
-        PYGI_INVOKE_STAGE_MARSHAL_IN_START:
-        PYGI_INVOKE_STAGE_MARSHAL_IN_IDLE:
+        case PYGI_INVOKE_STAGE_MARSHAL_IN_START:
+        case PYGI_INVOKE_STAGE_MARSHAL_IN_IDLE:
             g_free (data);
             break;
-        PYGI_INVOKE_STAGE_NATIVE_INVOKE_FAILED:
-        PYGI_INVOKE_STAGE_NATIVE_INVOKE_DONE:
+        case PYGI_INVOKE_STAGE_NATIVE_INVOKE_FAILED:
+        case PYGI_INVOKE_STAGE_NATIVE_INVOKE_DONE:
             if (arg_cache->transfer == GI_TRANSFER_NOTHING &&
                   arg_cache->direction == GI_DIRECTION_IN)
                 g_free (data);
             break;
-        PYGI_INVOKE_STAGE_MARSHAL_RETURN_START:
-        PYGI_INVOKE_STAGE_MARSHAL_RETURN_DONE:
-        PYGI_INVOKE_STAGE_MARSHAL_OUT_START:
-        PYGI_INVOKE_STAGE_MARSHAL_OUT_IDLE:
+        case PYGI_INVOKE_STAGE_MARSHAL_RETURN_START:
+        case PYGI_INVOKE_STAGE_MARSHAL_RETURN_DONE:
+        case PYGI_INVOKE_STAGE_MARSHAL_OUT_START:
+        case PYGI_INVOKE_STAGE_MARSHAL_OUT_IDLE:
             if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
                 g_free (data);
             break;
diff --git a/gi/pygi-marshal-cleanup.h b/gi/pygi-marshal-cleanup.h
index 60114db..acc9718 100644
--- a/gi/pygi-marshal-cleanup.h
+++ b/gi/pygi-marshal-cleanup.h
@@ -26,12 +26,13 @@
 
 G_BEGIN_DECLS
 
+void pygi_marshal_cleanup_args            (PyGIInvokeState   *state,
+                                           PyGICallableCache *cache,
+                                           gboolean           invoke_failure);
+
 void _pygi_marshal_cleanup_utf8           (PyGIInvokeState *state,
                                            PyGIArgCache    *arg_cache,
                                            gpointer         data);
-void pygi_marshal_cleanup_args            (PyGIInvokeState   *state,
-                                           PyGICallableCache *cache);
-
 void _pygi_marshal_cleanup_gvalue         (PyGIInvokeState *state,
                                            PyGIArgCache    *arg_cache,
                                            gpointer         data);



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