[pygobject] add a floating flag to pygobjects



commit 311a4f8035a95b41bc3c0a836c32b7a5bf2d9959
Author: John (J5) Palmieri <johnp redhat com>
Date:   Wed Sep 21 21:50:48 2011 -0400

    add a floating flag to pygobjects
    
    * this allows us to correctly refcount when custom gobjects are instantiated
      via g_object_new

 gi/_gobject/gobjectmodule.c     |    5 +++++
 gi/_gobject/pygobject-private.h |    3 +++
 gi/_gobject/pygobject.c         |   27 ++++++++++++++++++++++++++-
 gi/_gobject/pygobject.h         |    3 ++-
 4 files changed, 36 insertions(+), 2 deletions(-)
---
diff --git a/gi/_gobject/gobjectmodule.c b/gi/_gobject/gobjectmodule.c
index 2548f69..ac065a5 100644
--- a/gi/_gobject/gobjectmodule.c
+++ b/gi/_gobject/gobjectmodule.c
@@ -1066,6 +1066,11 @@ pygobject__g_instance_init(GTypeInstance   *instance,
         PyGILState_STATE state;
         state = pyglib_gil_state_ensure();
         wrapper = pygobject_new_full(object, FALSE, g_class);
+
+        /* float the wrapper ref here because we are going to orphan it
+         * so we don't destroy the wrapper. The next call to pygobject_new_full
+         * will take the ref */
+        pygobject_ref_float (wrapper);
         args = PyTuple_New(0);
         kwargs = PyDict_New();
         if (Py_TYPE(wrapper)->tp_init(wrapper, args, kwargs))
diff --git a/gi/_gobject/pygobject-private.h b/gi/_gobject/pygobject-private.h
index dabf0a4..1b1d6db 100644
--- a/gi/_gobject/pygobject-private.h
+++ b/gi/_gobject/pygobject-private.h
@@ -96,6 +96,9 @@ PyObject *pyg_integer_richcompare(PyObject *v,
 
 gboolean pyg_gerror_exception_check(GError **error);
 
+void pygobject_ref_float(PyGObject *self);
+void pygobject_ref_sink(PyGObject *self);
+
 /* from pygtype.h */
 extern PyTypeObject PyGTypeWrapper_Type;
 
diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c
index 48a9f18..0f0e5e2 100644
--- a/gi/_gobject/pygobject.c
+++ b/gi/_gobject/pygobject.c
@@ -560,6 +560,31 @@ pygobject_switch_to_toggle_ref(PyGObject *self)
     g_object_unref(self->obj);
 }
 
+/* Called when an custom gobject is initalized via g_object_new instead of
+   its constructor.  The next time the wrapper is access via 
+   pygobject_new_full it will sink the floating reference instead of
+   adding a new reference and causing a leak */
+ 
+void
+pygobject_ref_float(PyGObject *self)
+{
+    /* should only be floated once */
+    g_assert(!(self->private_flags.flags & PYGOBJECT_IS_FLOATING_REF));
+    
+    self->private_flags.flags |= PYGOBJECT_IS_FLOATING_REF;
+}
+
+/* Called by gobject_new_full, if the floating flag is set remove it, otherwise
+   ref the pyobject */
+void
+pygobject_ref_sink(PyGObject *self)
+{
+    if (self->private_flags.flags & PYGOBJECT_IS_FLOATING_REF)
+        self->private_flags.flags &= ~PYGOBJECT_IS_FLOATING_REF;
+    else
+        Py_INCREF ( (PyObject *) self);
+}
+
 /**
  * pygobject_register_wrapper:
  * @self: the wrapper instance
@@ -888,7 +913,7 @@ pygobject_new_full(GObject *obj, gboolean sink, gpointer g_class)
     /* we already have a wrapper for this object -- return it. */
     self = (PyGObject *)g_object_get_qdata(obj, pygobject_wrapper_key);
     if (self != NULL) {
-	Py_INCREF(self);
+	pygobject_ref_sink(self);
     } else {
 	/* create wrapper */
         PyGObjectData *inst_data = pyg_object_peek_inst_data(obj);
diff --git a/gi/_gobject/pygobject.h b/gi/_gobject/pygobject.h
index f728e15..8879fd0 100644
--- a/gi/_gobject/pygobject.h
+++ b/gi/_gobject/pygobject.h
@@ -23,7 +23,8 @@ struct _PyGClosure {
 };
 
 typedef enum {
-    PYGOBJECT_USING_TOGGLE_REF = 1 << 0
+    PYGOBJECT_USING_TOGGLE_REF = 1 << 0,
+    PYGOBJECT_IS_FLOATING_REF = 1 << 1
 } PyGObjectFlags;
 
   /* closures is just an alias for what is found in the



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