[pygobject/gi-boxed-remove-del: 3/3] boxed: remove __del__ implementation and free in tp_dealloc



commit b6827f9715dc5f679c817195b868aa0c9642c331
Author: Christoph Reiter <reiter christoph gmail com>
Date:   Tue Jan 15 14:45:55 2019 +0100

    boxed: remove __del__ implementation and free in tp_dealloc
    
    This allows us to assume that the wrapper is always valid and remove
    the _is_valid attribute.
    
    One difference now is that g_boxed_free() is called when the wrapper can no longer
    be used and that breaks the custom glib sources where g_boxed_free() triggers
    the finalize callback which tries to call into a method of the wrapper.
    
    To work around this provide a _clear_boxed() method which allows the wrapper
    to free the underlying boxed in __del__ where the wrapper is still usable.

 gi/overrides/GLib.py    |  5 ++++-
 gi/overrides/GObject.py |  8 ++------
 gi/pygi-boxed.c         | 34 ++++++++++++++++++----------------
 3 files changed, 24 insertions(+), 23 deletions(-)
---
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index e0ac233c..186902e8 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -524,7 +524,10 @@ class Source(GLib.Source):
     def __del__(self):
         if hasattr(self, '__pygi_custom_source'):
             self.destroy()
-        super(Source, self).__del__()
+            # XXX: We have to unref the underlying source while the Python
+            # wrapper is still valid, so the source can call into the
+            # wrapper methods for the finalized callback.
+            self._clear_boxed()
 
     def set_callback(self, fn, user_data=None):
         if hasattr(self, '__pygi_custom_source'):
diff --git a/gi/overrides/GObject.py b/gi/overrides/GObject.py
index a89ddc7d..4df27ab3 100644
--- a/gi/overrides/GObject.py
+++ b/gi/overrides/GObject.py
@@ -210,12 +210,8 @@ class Value(GObjectModule.Value):
                 self.set_value(py_value)
 
     def __del__(self):
-        if self._is_valid:
-            if self._free_on_dealloc and self.g_type != TYPE_INVALID:
-                self.unset()
-
-        # We must call base class __del__() after unset.
-        super(Value, self).__del__()
+        if self._free_on_dealloc and self.g_type != TYPE_INVALID:
+            self.unset()
 
     def set_boxed(self, boxed):
         # Workaround the introspection marshalers inability to know
diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c
index 32fa477c..90c57c72 100644
--- a/gi/pygi-boxed.c
+++ b/gi/pygi-boxed.c
@@ -35,13 +35,7 @@ struct _PyGIBoxed {
 };
 
 static void
-boxed_dealloc (PyGIBoxed *self)
-{
-    Py_TYPE (self)->tp_free ((PyObject *)self);
-}
-
-static PyObject *
-boxed_del (PyGIBoxed *self)
+boxed_clear (PyGIBoxed *self)
 {
     gpointer boxed = pyg_boxed_get_ptr (self);
 
@@ -55,10 +49,25 @@ boxed_del (PyGIBoxed *self)
         }
     }
     pyg_boxed_set_ptr (self, NULL);
+}
+
+static PyObject *
+boxed_clear_wrapper (PyGIBoxed *self)
+{
+    boxed_clear (self);
 
     Py_RETURN_NONE;
 }
 
+
+static void
+boxed_dealloc (PyGIBoxed *self)
+{
+    boxed_clear (self);
+
+    Py_TYPE (self)->tp_free ((PyObject *)self);
+}
+
 void *
 pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
 {
@@ -197,12 +206,6 @@ boxed_get_free_on_dealloc(PyGIBoxed *self, void *closure)
   return pygi_gboolean_to_py( ((PyGBoxed *)self)->free_on_dealloc );
 }
 
-static PyObject *
-boxed_get_is_valid (PyGIBoxed *self, void *closure)
-{
-  return pygi_gboolean_to_py (pyg_boxed_get_ptr (self) != NULL);
-}
-
 /**
  * pygi_boxed_copy_in_place:
  *
@@ -222,19 +225,18 @@ pygi_boxed_copy_in_place (PyGIBoxed *self)
     if (ptr)
         copy = g_boxed_copy (pygboxed->gtype, ptr);
 
-    boxed_del (self);
+    boxed_clear (self);
     pyg_boxed_set_ptr (pygboxed, copy);
     pygboxed->free_on_dealloc = TRUE;
 }
 
 static PyGetSetDef pygi_boxed_getsets[] = {
     { "_free_on_dealloc", (getter)boxed_get_free_on_dealloc, (setter)0 },
-    { "_is_valid", (getter)boxed_get_is_valid, (setter)0 },
     { NULL, 0, 0 }
 };
 
 static PyMethodDef boxed_methods[] = {
-    { "__del__", (PyCFunction)boxed_del, METH_NOARGS },
+    { "_clear_boxed", (PyCFunction)boxed_clear_wrapper, METH_NOARGS },
     { NULL, NULL, 0 }
 };
 


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