[glib] g_static_private_free: defer non-trivial destruction til after we unlock



commit b05f0b351c46a8f97bf7e9d62f5dd4074ca78486
Author: Simon McVittie <simon mcvittie collabora co uk>
Date:   Tue May 24 16:02:33 2011 +0100

    g_static_private_free: defer non-trivial destruction til after we unlock
    
    Bug: https://bugzilla.gnome.org/show_bug.cgi?id=642026
    Bug-NB: NB#257512

 glib/gthread.c |   31 ++++++++++++++++++++++++++++---
 1 files changed, 28 insertions(+), 3 deletions(-)
---
diff --git a/glib/gthread.c b/glib/gthread.c
index d32782f..b567be5 100644
--- a/glib/gthread.c
+++ b/glib/gthread.c
@@ -1762,6 +1762,7 @@ g_static_private_free (GStaticPrivate *private_key)
 {
   guint idx = private_key->index;
   GRealThread *thread;
+  GArray *garbage = NULL;
 
   if (!idx)
     return;
@@ -1789,15 +1790,39 @@ g_static_private_free (GStaticPrivate *private_key)
 
           if (ddestroy)
             {
-              G_UNLOCK (g_thread);
-              ddestroy (ddata);
-              G_LOCK (g_thread);
+              /* defer non-trivial destruction til after we've finished
+               * iterating, since we must continue to hold the lock */
+              if (garbage == NULL)
+                garbage = g_array_new (FALSE, TRUE,
+                                       sizeof (GStaticPrivateNode));
+
+              g_array_set_size (garbage, garbage->len + 1);
+
+              node = &g_array_index (garbage, GStaticPrivateNode,
+                                     garbage->len - 1);
+              node->data = ddata;
+              node->destroy = ddestroy;
             }
 	}
     }
   g_thread_free_indeces = g_slist_prepend (g_thread_free_indeces,
 					   GUINT_TO_POINTER (idx));
   G_UNLOCK (g_thread);
+
+  if (garbage)
+    {
+      guint i;
+
+      for (i = 0; i < garbage->len; i++)
+        {
+          GStaticPrivateNode *node;
+
+          node = &g_array_index (garbage, GStaticPrivateNode, i);
+          node->destroy (node->data);
+        }
+
+      g_array_free (garbage, TRUE);
+    }
 }
 
 /* GThread Extra Functions {{{1 ------------------------------------------- */



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