[gnome-builder/wip/gtk4-port: 405/736] libide/code: defer boxed object release to idle




commit b7eab51431ffa343802580dd7d49bcede7b583ee
Author: Christian Hergert <chergert redhat com>
Date:   Tue Apr 5 12:00:57 2022 -0700

    libide/code: defer boxed object release to idle
    
    We don't want to do this synchronously as causing the box to be released
    will result in g_object_run_dispose() being called which will disconnect
    all the signal handlers.
    
    That makes things difficult for plugins which might be racing against this
    situation and cannot be semmetric with add/remove of signals.

 src/libide/code/ide-buffer.c | 36 +++++++++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 7 deletions(-)
---
diff --git a/src/libide/code/ide-buffer.c b/src/libide/code/ide-buffer.c
index 48d62ed49..c900c4c4d 100644
--- a/src/libide/code/ide-buffer.c
+++ b/src/libide/code/ide-buffer.c
@@ -88,12 +88,12 @@ struct _IdeBuffer
   GFile                  *readlink_file;
 
   IdeTask                *in_flight_symbol_at_location;
-  gint                    in_flight_symbol_at_location_pos;
+  int                     in_flight_symbol_at_location_pos;
 
-  /* Scalars */
   guint                   change_count;
   guint                   settling_source;
-  gint                    hold;
+  int                     hold;
+  guint                   release_in_idle;
 
   /* Bit-fields */
   IdeBufferState          state : 3;
@@ -487,6 +487,7 @@ ide_buffer_dispose (GObject *object)
   g_assert (IDE_IS_MAIN_THREAD ());
 
   g_clear_handle_id (&self->settling_source, g_source_remove);
+  g_clear_handle_id (&self->release_in_idle, g_source_remove);
 
   /* Remove ourselves from the object-tree if necessary */
   if ((box = ide_object_box_from_object (object)) &&
@@ -3927,9 +3928,27 @@ ide_buffer_hold (IdeBuffer *self)
 
   self->hold++;
 
+  g_clear_handle_id (&self->release_in_idle, g_source_remove);
+
   return g_object_ref (self);
 }
 
+static gboolean
+ide_buffer_release_in_idle (gpointer data)
+{
+  IdeBuffer *self = data;
+  IdeObjectBox *box;
+
+  g_assert (IDE_IS_BUFFER (self));
+
+  self->release_in_idle = 0;
+
+  if ((box = ide_object_box_from_object (G_OBJECT (self))))
+    ide_object_destroy (IDE_OBJECT (box));
+
+  return G_SOURCE_REMOVE;
+}
+
 /**
  * ide_buffer_release:
  * @self: a #IdeBuffer
@@ -3952,10 +3971,13 @@ ide_buffer_release (IdeBuffer *self)
 
   if (self->hold == 0)
     {
-      IdeObjectBox *box = ide_object_box_from_object (G_OBJECT (self));
-
-      if (box != NULL)
-        ide_object_destroy (IDE_OBJECT (box));
+      g_assert (self->release_in_idle == 0);
+      self->release_in_idle =
+        g_idle_add_full (G_PRIORITY_DEFAULT,
+                         ide_buffer_release_in_idle,
+                         self,
+                         g_object_unref);
+      return;
     }
 
   g_object_unref (self);


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