glib r7054 - branches/glib-2-16/gobject



Author: matthiasc
Date: Tue Jun 17 02:58:11 2008
New Revision: 7054
URL: http://svn.gnome.org/viewvc/glib?rev=7054&view=rev

Log:
        * gtype.c (g_type_class_ref): fixed race condition where references to
        partially initialized classes could be handed out.


Modified:
   branches/glib-2-16/gobject/ChangeLog
   branches/glib-2-16/gobject/gtype.c

Modified: branches/glib-2-16/gobject/gtype.c
==============================================================================
--- branches/glib-2-16/gobject/gtype.c	(original)
+++ branches/glib-2-16/gobject/gtype.c	Tue Jun 17 02:58:11 2008
@@ -2363,20 +2363,19 @@
 g_type_class_ref (GType type)
 {
   TypeNode *node;
-  
-  /* optimize for common code path
-   */
+  GType ptype;
+
+  /* optimize for common code path */
   G_WRITE_LOCK (&type_rw_lock);
   node = lookup_type_node_I (type);
   if (node && node->is_classed && node->data &&
-      node->data->class.class && node->data->common.ref_count > 0)
+      node->data->class.class &&
+      node->data->class.init_state == INITIALIZED)
     {
       type_data_ref_Wm (node);
       G_WRITE_UNLOCK (&type_rw_lock);
-      
       return node->data->class.class;
     }
-  
   if (!node || !node->is_classed ||
       (node->data && node->data->common.ref_count < 1))
     {
@@ -2385,33 +2384,28 @@
 		 type_descriptive_name_I (type));
       return NULL;
     }
-
   type_data_ref_Wm (node);
+  ptype = NODE_PARENT_TYPE (node);
+  G_WRITE_UNLOCK (&type_rw_lock);
 
+  g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
+  /* here, we either have node->data->class.class == NULL, or a recursive
+   * call to g_type_class_ref() with a partly initialized class, or
+   * node->data->class.init_state == INITIALIZED, because any
+   * concurrently running initialization was guarded by class_init_rec_mutex.
+   */
   if (!node->data->class.class) /* class uninitialized */
     {
-      GType ptype = NODE_PARENT_TYPE (node);
-      GTypeClass *pclass = NULL;
-      G_WRITE_UNLOCK (&type_rw_lock);
-      g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
-      if (ptype)
-        {
-          pclass = g_type_class_ref (ptype);
-          G_WRITE_LOCK (&type_rw_lock);
-          node = lookup_type_node_I (type);
-          if (node->data->class.class)
-            INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
-        }
-      else
-        {
-          G_WRITE_LOCK (&type_rw_lock);
-          node = lookup_type_node_I (type);
-        }
-      if (!node->data->class.class) /* class could have been initialized meanwhile */
-        type_class_init_Wm (node, pclass);
+      /* acquire reference on parent class */
+      GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
+      G_WRITE_LOCK (&type_rw_lock);
+      if (node->data->class.class) /* class was initialized during parent class initialization? */
+        INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
+      type_class_init_Wm (node, pclass);
       G_WRITE_UNLOCK (&type_rw_lock);
-      g_static_rec_mutex_unlock (&class_init_rec_mutex);
     }
+  g_static_rec_mutex_unlock (&class_init_rec_mutex);
+
   return node->data->class.class;
 }
 



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