[gnome-builder] egg-signal-group: Weak ref object in connect_object()



commit 56ea3d69f961debe3ab7f7f1dbc2223c2fe2e929
Author: Garrett Regier <garrettregier gmail com>
Date:   Wed May 13 16:38:43 2015 -0700

    egg-signal-group: Weak ref object in connect_object()
    
    The handler must be removed and freed
    when the object dies.

 contrib/egg/egg-signal-group.c |   61 ++++++++++++++++++++++++++++++++++-----
 1 files changed, 53 insertions(+), 8 deletions(-)
---
diff --git a/contrib/egg/egg-signal-group.c b/contrib/egg/egg-signal-group.c
index 70caf21..e4ddf7a 100644
--- a/contrib/egg/egg-signal-group.c
+++ b/contrib/egg/egg-signal-group.c
@@ -70,10 +70,12 @@ struct _EggSignalGroupClass
 
 typedef struct
 {
-  gulong       handler_id;
-  GClosure    *closure;
-  const gchar *detailed_signal;
-  guint        connect_after : 1;
+  EggSignalGroup *group;
+  gulong          handler_id;
+  GClosure       *closure;
+  GObject        *object;
+  const gchar    *detailed_signal;
+  guint           connect_after : 1;
 } SignalHandler;
 
 G_DEFINE_TYPE (EggSignalGroup, egg_signal_group, G_TYPE_OBJECT)
@@ -120,6 +122,33 @@ egg_signal_group__target_weak_notify (gpointer  data,
 }
 
 static void
+egg_signal_group__connect_object_weak_notify (gpointer  data,
+                                              GObject  *where_object_was)
+{
+  EggSignalGroup *self = data;
+  gsize i;
+
+  g_assert (EGG_IS_SIGNAL_GROUP (self));
+  g_assert (where_object_was != NULL);
+
+  for (i = 0; i < self->handlers->len; ++i)
+    {
+      SignalHandler *handler;
+
+      handler = g_ptr_array_index (self->handlers, i);
+
+      if (handler->object == where_object_was)
+        {
+          handler->object = NULL;
+          g_ptr_array_remove_index_fast (self->handlers, i);
+          return;
+        }
+    }
+
+  g_critical ("Failed to find handler for %p", where_object_was);
+}
+
+static void
 egg_signal_group_bind_handler (EggSignalGroup *self,
                                SignalHandler  *handler)
 {
@@ -366,6 +395,14 @@ signal_handler_free (gpointer data)
 {
   SignalHandler *handler = data;
 
+  if (handler->object != NULL)
+    {
+      g_object_weak_unref (handler->object,
+                           egg_signal_group__connect_object_weak_notify,
+                           handler->group);
+      handler->object = NULL;
+    }
+
   g_clear_pointer (&handler->closure, g_closure_unref);
   handler->handler_id = 0;
   handler->detailed_signal = NULL;
@@ -568,17 +605,25 @@ egg_signal_group_connect_full (EggSignalGroup *self,
   else
     closure = g_cclosure_new (callback, data, notify);
 
-  /* This is what g_cclosure_new_object() does */
-  if (is_object)
-    g_object_watch_closure (data, closure);
-
   handler = g_slice_new0 (SignalHandler);
+  handler->group = self;
   handler->detailed_signal = g_intern_string (detailed_signal);
   handler->closure = g_closure_ref (closure);
   handler->connect_after = ((flags & G_CONNECT_AFTER) != 0);
 
   g_closure_sink (closure);
 
+  if (is_object)
+    {
+      /* This is what g_cclosure_new_object() does */
+      g_object_watch_closure (data, closure);
+
+      handler->object = data;
+      g_object_weak_ref (data,
+                         egg_signal_group__connect_object_weak_notify,
+                         self);
+    }
+
   g_ptr_array_add (self->handlers, handler);
 
   if (self->target != NULL)


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