[pygobject/invoke-rewrite] [gi-invoke-ng] create new framework for cleaning up args
- From: John Palmieri <johnp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject/invoke-rewrite] [gi-invoke-ng] create new framework for cleaning up args
- Date: Tue, 12 Apr 2011 18:52:09 +0000 (UTC)
commit 12aa4e6376366ca9d758434f6544c9c70a1e5df8
Author: John (J5) Palmieri <johnp redhat com>
Date: Tue Apr 12 14:48:16 2011 -0400
[gi-invoke-ng] create new framework for cleaning up args
* we now have a state machine so we know what point in the marshalling process
we are and which args need to be cleaned up
* call the cleanup functions after invoking the gi callable, after marshalling
the out parameters and at any time an error occures
gi/Makefile.am | 4 ++-
gi/pygi-cache.c | 25 +++++++------
gi/pygi-cache.h | 5 ++-
gi/pygi-invoke-ng.c | 34 ++++++++++++++---
gi/pygi-invoke-state-struct.h | 13 +++++++
gi/pygi-marshal-cleanup.c | 81 +++++++++++++++++++++++++++++++++++++++++
gi/pygi-marshal-cleanup.h | 43 ++++++++++++++++++++++
gi/pygi-marshal.c | 1 +
8 files changed, 187 insertions(+), 19 deletions(-)
---
diff --git a/gi/Makefile.am b/gi/Makefile.am
index 8bd5057..500828d 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -64,7 +64,9 @@ _gi_la_SOURCES += \
pygi-cache.h \
pygi-cache.c \
pygi-marshal.c \
- pygi-marshal.h
+ pygi-marshal.h \
+ pygi-marshal-cleanup.c \
+ pygi-marshal-cleanup.h
else
_gi_la_SOURCES += \
pygi-invoke.c
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 323bda7..7a38db5 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -22,6 +22,7 @@
#include "pygi-info.h"
#include "pygi-cache.h"
#include "pygi-marshal.h"
+#include "pygi-marshal-cleanup.h"
#include "pygi-type.h"
#include <girepository.h>
@@ -540,7 +541,7 @@ _arg_cache_out_array_setup (PyGIArgCache *arg_cache,
if (seq_cache->len_arg_index >= 0) {
PyGIArgCache *aux_cache = callable_cache->args_cache[seq_cache->len_arg_index];
- if (seq_cache->len_argindex < arg_index)
+ if (seq_cache->len_arg_index < arg_index)
callable_cache->n_out_aux_args++;
if (aux_cache != NULL) {
@@ -637,11 +638,6 @@ _arg_cache_out_interface_union_setup (PyGIArgCache *arg_cache,
arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
}
-static void
-_g_slice_free_gvalue_func (GValue *value) {
- g_slice_free (GValue, value);
-}
-
static inline void
_arg_cache_in_interface_struct_setup (PyGIArgCache *arg_cache,
GIInterfaceInfo *iface_info,
@@ -650,10 +646,12 @@ _arg_cache_in_interface_struct_setup (PyGIArgCache *arg_cache,
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
- if (iface_cache->g_type == G_TYPE_VALUE)
- arg_cache->cleanup = _g_slice_free_gvalue_func;
+ if (iface_cache->g_type == G_TYPE_VALUE &&
+ arg_cache->transfer == GI_TRANSFER_NOTHING &&
+ arg_cache->direction == GI_DIRECTION_IN)
+ arg_cache->cleanup = _pygi_marshal_cleanup_gvalue;
if (iface_cache->g_type == G_TYPE_CLOSURE)
- arg_cache->cleanup = g_closure_unref;
+ arg_cache->cleanup = _pygi_marshal_cleanup_closure_unref;
}
static inline void
@@ -664,6 +662,11 @@ _arg_cache_out_interface_struct_setup (PyGIArgCache *arg_cache,
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
+
+ if (iface_cache->g_type == G_TYPE_VALUE &&
+ arg_cache->transfer != GI_TRANSFER_NOTHING &&
+ arg_cache->direction == GI_DIRECTION_OUT)
+ arg_cache->cleanup = _pygi_marshal_cleanup_gvalue;
}
static inline void
@@ -671,8 +674,6 @@ _arg_cache_in_interface_object_setup (PyGIArgCache *arg_cache,
GITransfer transfer)
{
arg_cache->in_marshaller = _pygi_marshal_in_interface_object;
- if (transfer == GI_TRANSFER_EVERYTHING)
- arg_cache->cleanup = (GDestroyNotify)g_object_unref;
}
static inline void
@@ -680,6 +681,8 @@ _arg_cache_out_interface_object_setup (PyGIArgCache *arg_cache,
GITransfer transfer)
{
arg_cache->out_marshaller = _pygi_marshal_out_interface_object;
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
+ arg_cache->cleanup = _pygi_marshal_cleanup_object_unref;
}
static inline void
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index ec8df29..8023787 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -44,6 +44,9 @@ typedef PyObject *(*PyGIMarshalOutFunc) (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
GIArgument *arg);
+typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer *data);
typedef enum {
/* Not an AUX type */
PYGI_AUX_TYPE_NONE = 0,
@@ -68,8 +71,8 @@ struct _PyGIArgCache
PyGIMarshalInFunc in_marshaller;
PyGIMarshalOutFunc out_marshaller;
- GDestroyNotify cleanup;
+ PyGIMarshalCleanupFunc cleanup;
GDestroyNotify destroy_notify;
gssize c_arg_index;
diff --git a/gi/pygi-invoke-ng.c b/gi/pygi-invoke-ng.c
index c58a217..dc5bd70 100644
--- a/gi/pygi-invoke-ng.c
+++ b/gi/pygi-invoke-ng.c
@@ -84,6 +84,7 @@ _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
PyObject *py_args,
PyObject *kwargs)
{
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_IN_START;
state->py_in_args = py_args;
state->n_py_in_args = PySequence_Length (py_args);
@@ -192,6 +193,8 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
PyGIArgCache *arg_cache = cache->args_cache[i];
PyObject *py_arg = NULL;
+ state->current_arg = in_count;
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_IN_START;
switch (arg_cache->direction) {
case GI_DIRECTION_IN:
state->args[i] = &(state->in_args[in_count]);
@@ -290,6 +293,8 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
c_arg);
if (!success)
return FALSE;
+
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_IN_IDLE;
}
}
@@ -305,7 +310,10 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
int total_out_args = cache->n_out_args;
gboolean has_return = FALSE;
+ state->current_arg = 0;
+
if (cache->return_cache) {
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_RETURN_START;
if (cache->is_constructor) {
if (state->return_arg.v_pointer == NULL) {
PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
@@ -320,6 +328,8 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
if (py_return == NULL)
return NULL;
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_RETURN_DONE;
+
if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) {
total_out_args++;
has_return = TRUE;
@@ -332,13 +342,17 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
py_out = py_return;
} else if (total_out_args == 1) {
/* if we get here there is one out arg an no return */
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_OUT_START;
PyGIArgCache *arg_cache = (PyGIArgCache *)cache->out_args->data;
py_out = arg_cache->out_marshaller (state,
cache,
arg_cache,
state->args[arg_cache->c_arg_index]);
+ if (py_out == NULL)
+ return NULL;
+
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_OUT_IDLE;
} else {
- int out_cache_index = 0;
int py_arg_index = 0;
GSList *cache_item = cache->out_args;
/* return a tuple */
@@ -350,13 +364,19 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
for(; py_arg_index < total_out_args; py_arg_index++) {
PyGIArgCache *arg_cache = (PyGIArgCache *)cache_item->data;
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_OUT_START;
PyObject *py_obj = arg_cache->out_marshaller (state,
cache,
arg_cache,
state->args[arg_cache->c_arg_index]);
- if (py_obj == NULL)
+ if (py_obj == NULL) {
+ Py_DECREF (py_out);
return NULL;
+ }
+
+ state->current_arg++;
+ state->stage = PYGI_INVOKE_STAGE_MARSHAL_OUT_IDLE;
PyTuple_SET_ITEM (py_out, py_arg_index, py_obj);
cache_item = cache_item->next;
@@ -371,7 +391,7 @@ _wrap_g_callable_info_invoke (PyGIBaseInfo *self,
PyObject *kwargs)
{
PyGIInvokeState state = { 0, };
- PyObject *ret;
+ PyObject *ret = NULL;
if (self->cache == NULL) {
self->cache = _pygi_callable_cache_new (self->info);
@@ -386,11 +406,13 @@ _wrap_g_callable_info_invoke (PyGIBaseInfo *self,
if (!_invoke_callable (&state, self->cache, self->info))
goto err;
+ pygi_marshal_cleanup_args (&state, self->cache);
+
ret = _invoke_marshal_out_args (&state, self->cache);
- _invoke_state_clear (&state, self->cache);
- return ret;
+ state.stage = PYGI_INVOKE_STAGE_DONE;
err:
+ pygi_marshal_cleanup_args (&state, self->cache);
_invoke_state_clear (&state, self->cache);
- return NULL;
+ return ret;
}
diff --git a/gi/pygi-invoke-state-struct.h b/gi/pygi-invoke-state-struct.h
index 3147ee8..0643960 100644
--- a/gi/pygi-invoke-state-struct.h
+++ b/gi/pygi-invoke-state-struct.h
@@ -7,11 +7,24 @@
G_BEGIN_DECLS
+typedef enum {
+ PYGI_INVOKE_STAGE_MARSHAL_IN_START,
+ PYGI_INVOKE_STAGE_MARSHAL_IN_IDLE,
+ PYGI_INVOKE_STAGE_MARSHAL_RETURN_START,
+ PYGI_INVOKE_STAGE_MARSHAL_RETURN_DONE,
+ PYGI_INVOKE_STAGE_MARSHAL_OUT_START,
+ PYGI_INVOKE_STAGE_MARSHAL_OUT_IDLE,
+ PYGI_INVOKE_STAGE_DONE
+} PyGIInvokeStage;
+
typedef struct _PyGIInvokeState
{
PyObject *py_in_args;
PyObject *constructor_class;
gssize n_py_in_args;
+ gssize current_arg;
+
+ PyGIInvokeStage stage;
GType implementor_gtype;
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
new file mode 100644
index 0000000..aaab7b3
--- /dev/null
+++ b/gi/pygi-marshal-cleanup.c
@@ -0,0 +1,81 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp redhat com>, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+ #include "pygi-marshal-cleanup.h"
+ #include <glib.h>
+
+void
+pygi_marshal_cleanup_args (PyGIInvokeState *state,
+ PyGICallableCache *cache)
+{
+ switch (state->stage) {
+ case PYGI_INVOKE_STAGE_MARSHAL_IN_IDLE:
+ /* current_arg has been marshalled so increment to start with
+ next arg */
+ state->current_arg++;
+ case PYGI_INVOKE_STAGE_MARSHAL_IN_START:
+ /* we have not yet invoked so we only need to clean up
+ the in args */
+
+ break;
+ 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:
+ break;
+ case PYGI_INVOKE_STAGE_MARSHAL_RETURN_START:
+ break;
+ }
+}
+
+ void
+ _pygi_marshal_cleanup_gvalue (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer data)
+{
+ /*
+ if (arg_cache->direction == GI_DIRECTION_IN)
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
+ g_slice_free (GValue, data);
+ */
+}
+
+void
+_pygi_marshal_cleanup_closure_unref (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer data)
+{
+ g_closure_unref ( (GClosure *)data);
+}
+
+void
+_pygi_marshal_cleanup_object_unref (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer data)
+{
+ g_object_unref ( (GObject *)data);
+}
+
diff --git a/gi/pygi-marshal-cleanup.h b/gi/pygi-marshal-cleanup.h
new file mode 100644
index 0000000..dc5d66c
--- /dev/null
+++ b/gi/pygi-marshal-cleanup.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp redhat com>, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef __PYGI_MARSHAL_CLEANUP_H__
+#define __PYGI_MARSHAL_CLEANUP_H__
+
+#include "pygi-private.h"
+
+G_BEGIN_DECLS
+
+void pygi_marshal_cleanup_args (PyGIInvokeState *state,
+ PyGICallableCache *cache);
+
+void _pygi_marshal_cleanup_gvalue (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer data);
+void _pygi_marshal_cleanup_closure_unref (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer data);
+void _pygi_marshal_cleanup_object_unref (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ gpointer data);
+G_END_DECLS
+
+#endif /* __PYGI_MARSHAL_CLEANUP_H__ */
diff --git a/gi/pygi-marshal.c b/gi/pygi-marshal.c
index 62606b4..64a494e 100644
--- a/gi/pygi-marshal.c
+++ b/gi/pygi-marshal.c
@@ -31,6 +31,7 @@
#include <pyglib-python-compat.h>
#include "pygi-cache.h"
+#include "pygi-marshal-cleanup.h"
/*** argument marshaling and validating routines ***/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]