check private instance data after initialization.
authorTim Janik <timj@gtk.org>
Tue, 19 Aug 2003 03:25:46 +0000 (03:25 +0000)
committerTim Janik <timj@src.gnome.org>
Tue, 19 Aug 2003 03:25:46 +0000 (03:25 +0000)
Tue Aug 19 05:21:04 2003  Tim Janik  <timj@gtk.org>

        * testgobject.c (main): check private instance data after
        initialization.

        * gtype.c: for instances with private data, store the real class
        pointer in a bsearch array during class initialization.
        (g_type_instance_get_private): fetch the real class of
        an instance from the bsearch array if necessary.

gobject/ChangeLog
gobject/gtype.c
gobject/testgobject.c

index dbf542b..2e37f1d 100644 (file)
@@ -1,3 +1,13 @@
+Tue Aug 19 05:21:04 2003  Tim Janik  <timj@gtk.org>
+
+       * testgobject.c (main): check private instance data after
+       initialization.
+
+       * gtype.c: for instances with private data, store the real class
+       pointer in a bsearch array during class initialization.
+       (g_type_instance_get_private): fetch the real class of
+       an instance from the bsearch array if necessary.
+
 Tue Aug 19 04:08:14 2003  Tim Janik  <timj@gtk.org>
 
        * gvalue.c: adapt to new gbsearcharray.h code.
index 891053b..faf4481 100644 (file)
@@ -25,6 +25,7 @@
 
 #include       "gtypeplugin.h"
 #include       "gvaluecollector.h"
+#include       "gbsearcharray.h"
 #include       <string.h>
 
 
@@ -1374,6 +1375,68 @@ type_total_instance_size_I (TypeNode *node)
 }
 
 /* --- type structure creation/destruction --- */
+typedef struct {
+  gpointer instance;
+  gpointer class;
+} InstanceRealClass;
+static gint
+instance_real_class_cmp (gconstpointer p1,
+                         gconstpointer p2)
+{
+  const InstanceRealClass *irc1 = p1;
+  const InstanceRealClass *irc2 = p2;
+  guint8 *i1 = irc1->instance;
+  guint8 *i2 = irc2->instance;
+  return G_BSEARCH_ARRAY_CMP (i1, i2);
+}
+G_LOCK_DEFINE_STATIC (instance_real_class);
+static GBSearchArray *instance_real_class_bsa = NULL;
+static GBSearchConfig instance_real_class_bconfig = {
+  sizeof (InstanceRealClass),
+  instance_real_class_cmp,
+  0,
+};
+static inline void
+instance_real_class_set (gpointer    instance,
+                         GTypeClass *class)
+{
+  InstanceRealClass key;
+  key.instance = instance;
+  key.class = class;
+  G_LOCK (instance_real_class);
+  if (!instance_real_class_bsa)
+    instance_real_class_bsa = g_bsearch_array_create (&instance_real_class_bconfig);
+  instance_real_class_bsa = g_bsearch_array_replace (instance_real_class_bsa, &instance_real_class_bconfig, &key);
+  G_UNLOCK (instance_real_class);
+}
+static inline void
+instance_real_class_remove (gpointer instance)
+{
+  InstanceRealClass key, *node;
+  guint index;
+  key.instance = instance;
+  G_LOCK (instance_real_class);
+  node = g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key);
+  index = g_bsearch_array_get_index (instance_real_class_bsa, &instance_real_class_bconfig, node);
+  instance_real_class_bsa = g_bsearch_array_remove (instance_real_class_bsa, &instance_real_class_bconfig, index);
+  if (!g_bsearch_array_get_n_nodes (instance_real_class_bsa))
+    {
+      g_bsearch_array_free (instance_real_class_bsa, &instance_real_class_bconfig);
+      instance_real_class_bsa = NULL;
+    }
+  G_UNLOCK (instance_real_class);
+}
+static inline GTypeClass*
+instance_real_class_get (gpointer instance)
+{
+  InstanceRealClass key, *node;
+  key.instance = instance;
+  G_LOCK (instance_real_class);
+  node = g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key);
+  G_UNLOCK (instance_real_class);
+  return node ? node->class : NULL;
+}
+
 GTypeInstance*
 g_type_create_instance (GType type)
 {
@@ -1428,6 +1491,9 @@ g_type_create_instance (GType type)
     }
   else
     instance = g_malloc0 (total_instance_size);        /* fine without read lock */
+
+  if (node->data->instance.private_size)
+    instance_real_class_set (instance, class);
   for (i = node->n_supers; i > 0; i--)
     {
       TypeNode *pnode;
@@ -1439,8 +1505,10 @@ g_type_create_instance (GType type)
          pnode->data->instance.instance_init (instance, class);
        }
     }
+  if (node->data->instance.private_size)
+    instance_real_class_remove (instance);
+
   instance->g_class = class;
-  
   if (node->data->instance.instance_init)
     node->data->instance.instance_init (instance, class);
   
@@ -3119,11 +3187,20 @@ g_type_instance_get_private (GTypeInstance *instance,
   TypeNode *instance_node;
   TypeNode *private_node;
   TypeNode *parent_node;
+  GTypeClass *class;
   gsize offset;
 
   g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
-  
-  instance_node = lookup_type_node_I (instance->g_class->g_type);
+
+  /* while instances are initialized, their class pointers change,
+   * so figure the instances real class first
+   */
+  if (instance_real_class_bsa)
+    class = instance_real_class_get (instance);
+  else
+    class = instance->g_class;
+
+  instance_node = lookup_type_node_I (class->g_type);
   if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable))
     {
       g_warning ("instance of invalid non-instantiatable type `%s'",
index 7ea341e..6f7832a 100644 (file)
@@ -222,6 +222,7 @@ test_object_check_private_init (TestObject *tobject)
 
   priv = TEST_OBJECT_GET_PRIVATE (tobject);
 
+  g_print ("private data during initialization: %u == %u\n", priv->dummy1, 54321);
   g_assert (priv->dummy1 == 54321);
 }
 static gboolean
@@ -379,6 +380,7 @@ main (int   argc,
   GType type;
   TestObject *sigarg;
   DerivedObject *dobject;
+  TestObjectPrivate *priv;
   gchar *string = NULL;
 
   g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
@@ -412,6 +414,10 @@ main (int   argc,
   g_print ("MAIN: call iface print-string on test and derived object:\n");
   iface_print_string (TEST_IFACE (sigarg), "iface-string-from-test-type");
   iface_print_string (TEST_IFACE (dobject), "iface-string-from-derived-type");
+
+  priv = TEST_OBJECT_GET_PRIVATE (dobject);
+  g_print ("private data after initialization: %u == %u\n", priv->dummy1, 54321);
+  g_assert (priv->dummy1 == 54321);
   
   g_object_unref (sigarg);
   g_object_unref (dobject);