Remove g_trap_instance_signals as well
[platform/upstream/glib.git] / gobject / gobject.c
index 38bbcca..1e37f4a 100644 (file)
@@ -176,7 +176,7 @@ static void g_object_dispatch_properties_changed    (GObject        *object,
 static guint               object_floating_flag_handler (GObject        *object,
                                                          gint            job);
 
-static void object_interface_check_properties           (gpointer        func_data,
+static void object_interface_check_properties           (gpointer        check_data,
                                                         gpointer        g_iface);
 
 /* --- typedefs --- */
@@ -197,11 +197,10 @@ static GQuark                 quark_closure_array = 0;
 static GQuark              quark_weak_refs = 0;
 static GQuark              quark_toggle_refs = 0;
 static GQuark               quark_notify_queue;
+static GQuark               quark_in_construction;
 static GParamSpecPool      *pspec_pool = NULL;
 static gulong              gobject_signals[LAST_SIGNAL] = { 0, };
 static guint (*floating_flag_handler) (GObject*, gint) = object_floating_flag_handler;
-G_LOCK_DEFINE_STATIC (construction_mutex);
-static GSList *construction_objects = NULL;
 /* qdata pointing to GSList<GWeakRef *>, protected by weak_locations_lock */
 static GQuark              quark_weak_locations = 0;
 static GRWLock              weak_locations_lock;
@@ -314,7 +313,6 @@ g_object_notify_queue_add (GObject            *object,
 #ifdef G_ENABLE_DEBUG
 #define        IF_DEBUG(debug_type)    if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
 G_LOCK_DEFINE_STATIC     (debug_objects);
-static volatile GObject *g_trap_object_ref = NULL;
 static guint            debug_objects_count = 0;
 static GHashTable      *debug_objects_ht = NULL;
 
@@ -451,6 +449,7 @@ g_object_do_class_init (GObjectClass *class)
   quark_weak_locations = g_quark_from_static_string ("GObject-weak-locations");
   quark_toggle_refs = g_quark_from_static_string ("GObject-toggle-references");
   quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
+  quark_in_construction = g_quark_from_static_string ("GObject-in-construction");
   pspec_pool = g_param_spec_pool_new (TRUE);
 
   class->constructor = g_object_constructor;
@@ -508,7 +507,7 @@ install_property_internal (GType       g_type,
 {
   if (g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type, FALSE))
     {
-      g_warning ("When installing property: type `%s' already has a property named `%s'",
+      g_warning ("When installing property: type '%s' already has a property named '%s'",
                 g_type_name (g_type),
                 pspec->name);
       return;
@@ -540,8 +539,10 @@ g_object_class_install_property (GObjectClass *class,
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
   if (CLASS_HAS_DERIVED_CLASS (class))
-    g_error ("Attempt to add property %s::%s to class after it was derived",
-            G_OBJECT_CLASS_NAME (class), pspec->name);
+    g_error ("Attempt to add property %s::%s to class after it was derived", G_OBJECT_CLASS_NAME (class), pspec->name);
+
+  if (!g_type_is_in_init (G_OBJECT_CLASS_TYPE (class)))
+    g_warning ("Attempt to add property %s::%s after class was initialised", G_OBJECT_CLASS_NAME (class), pspec->name);
 
   class->flags |= CLASS_HAS_PROPS_FLAG;
 
@@ -653,6 +654,9 @@ g_object_class_install_properties (GObjectClass  *oclass,
     g_error ("Attempt to add properties to %s after it was derived",
              G_OBJECT_CLASS_NAME (oclass));
 
+  if (!g_type_is_in_init (G_OBJECT_CLASS_TYPE (oclass)))
+    g_warning ("Attempt to add properties to %s after it was initialised", G_OBJECT_CLASS_NAME (oclass));
+
   oclass_type = G_OBJECT_CLASS_TYPE (oclass);
   parent_type = g_type_parent (oclass_type);
 
@@ -945,6 +949,12 @@ g_object_interface_list_properties (gpointer      g_iface,
   return pspecs;
 }
 
+static inline gboolean
+object_in_construction (GObject *object)
+{
+  return g_datalist_id_get_data (&object->qdata, quark_in_construction) != NULL;
+}
+
 static void
 g_object_init (GObject         *object,
               GObjectClass     *class)
@@ -960,10 +970,8 @@ g_object_init (GObject             *object,
 
   if (CLASS_HAS_CUSTOM_CONSTRUCTOR (class))
     {
-      /* enter construction list for notify_queue_thaw() and to allow construct-only properties */
-      G_LOCK (construction_mutex);
-      construction_objects = g_slist_prepend (construction_objects, object);
-      G_UNLOCK (construction_mutex);
+      /* mark object in-construction for notify_queue_thaw() and to allow construct-only properties */
+      g_datalist_id_set_data (&object->qdata, quark_in_construction, object);
     }
 
 #ifdef G_ENABLE_DEBUG
@@ -1016,6 +1024,12 @@ g_object_real_dispose (GObject *object)
 static void
 g_object_finalize (GObject *object)
 {
+  if (object_in_construction (object))
+    {
+      g_error ("object %s %p finalized while still in-construction",
+               G_OBJECT_TYPE_NAME (object), object);
+    }
+
   g_datalist_clear (&object->qdata);
   
 #ifdef G_ENABLE_DEBUG
@@ -1147,6 +1161,11 @@ g_object_notify_by_spec_internal (GObject    *object,
  * When possible, eg. when signaling a property change from within the class
  * that registered the property, you should use g_object_notify_by_pspec()
  * instead.
+ *
+ * Note that emission of the notify signal may be blocked with
+ * g_object_freeze_notify(). In this case, the signal emissions are queued
+ * and will be emitted (in reverse order) when g_object_thaw_notify() is
+ * called.
  */
 void
 g_object_notify (GObject     *object,
@@ -1170,7 +1189,7 @@ g_object_notify (GObject     *object,
                                    TRUE);
 
   if (!pspec)
-    g_warning ("%s: object class `%s' has no property named `%s'",
+    g_warning ("%s: object class '%s' has no property named '%s'",
               G_STRFUNC,
               G_OBJECT_TYPE_NAME (object),
               property_name);
@@ -1233,6 +1252,9 @@ g_object_notify_by_pspec (GObject    *object,
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
+  if (g_atomic_int_get (&object->ref_count) == 0)
+    return;
+
   g_object_ref (object);
   g_object_notify_by_spec_internal (object, pspec);
   g_object_unref (object);
@@ -1247,7 +1269,8 @@ g_object_notify_by_pspec (GObject    *object,
  * and when it reaches zero, queued "notify" signals are emitted.
  *
  * Duplicate notifications for each property are squashed so that at most one
- * #GObject::notify signal is emitted for each property.
+ * #GObject::notify signal is emitted for each property, in the reverse order
+ * in which they have been queued.
  *
  * It is an error to call this function when the freeze count is zero.
  */
@@ -1336,7 +1359,7 @@ object_set_property (GObject             *object,
   /* provide a copy to work from, convert (if necessary) and validate */
   g_value_init (&tmp_value, pspec->value_type);
   if (!g_value_transform (value, &tmp_value))
-    g_warning ("unable to set property `%s' of type `%s' from value of type `%s'",
+    g_warning ("unable to set property '%s' of type '%s' from value of type '%s'",
               pspec->name,
               g_type_name (pspec->value_type),
               G_VALUE_TYPE_NAME (value));
@@ -1344,7 +1367,7 @@ object_set_property (GObject             *object,
     {
       gchar *contents = g_strdup_value_contents (value);
 
-      g_warning ("value \"%s\" of type `%s' is invalid or out of range for property `%s' of type `%s'",
+      g_warning ("value \"%s\" of type '%s' is invalid or out of range for property '%s' of type '%s'",
                 contents,
                 G_VALUE_TYPE_NAME (value),
                 pspec->name,
@@ -1366,7 +1389,7 @@ object_set_property (GObject             *object,
 }
 
 static void
-object_interface_check_properties (gpointer func_data,
+object_interface_check_properties (gpointer check_data,
                                   gpointer g_iface)
 {
   GTypeInterface *iface_class = g_iface;
@@ -1554,38 +1577,6 @@ g_object_new (GType         object_type,
   return object;
 }
 
-static gboolean
-slist_maybe_remove (GSList       **slist,
-                    gconstpointer  data)
-{
-  GSList *last = NULL, *node = *slist;
-  while (node)
-    {
-      if (node->data == data)
-        {
-          if (last)
-            last->next = node->next;
-          else
-            *slist = node->next;
-          g_slist_free_1 (node);
-          return TRUE;
-        }
-      last = node;
-      node = last->next;
-    }
-  return FALSE;
-}
-
-static inline gboolean
-object_in_construction_list (GObject *object)
-{
-  gboolean in_construction;
-  G_LOCK (construction_mutex);
-  in_construction = g_slist_find (construction_objects, object) != NULL;
-  G_UNLOCK (construction_mutex);
-  return in_construction;
-}
-
 static gpointer
 g_object_new_with_custom_constructor (GObjectClass          *class,
                                       GObjectConstructParam *params,
@@ -1662,25 +1653,23 @@ g_object_new_with_custom_constructor (GObjectClass          *class,
   g_free (cvalues);
 
   /* There is code in the wild that relies on being able to return NULL
-   * from its custom constructor.  This was never a supported operation
-   * and will leak memory, but since the code is already out there...
+   * from its custom constructor.  This was never a supported operation,
+   * but since the code is already out there...
    */
   if (object == NULL)
     {
-      g_critical ("Custom constructor for class %s returned NULL (which is invalid).  Unable to remove object "
-                  "from construction_objects list, so memory was probably just leaked.  Please use GInitable "
-                  "instead.", G_OBJECT_CLASS_NAME (class));
+      g_critical ("Custom constructor for class %s returned NULL (which is invalid). "
+                  "Please use GInitable instead.", G_OBJECT_CLASS_NAME (class));
       return NULL;
     }
 
-  /* g_object_init() will have added us to the construction_objects
-   * list.  Check if we're in it (and remove us) in order to find
-   * out if we were newly-constructed or this is an already-existing
-   * singleton (in which case we should not do 'constructed').
+  /* g_object_init() will have marked the object as being in-construction.
+   * Check if the returned object still is so marked, or if this is an
+   * already-existing singleton (in which case we should not do 'constructed').
    */
-  G_LOCK (construction_mutex);
-  newly_constructed = slist_maybe_remove (&construction_objects, object);
-  G_UNLOCK (construction_mutex);
+  newly_constructed = object_in_construction (object);
+  if (newly_constructed)
+    g_datalist_id_set_data (&object->qdata, quark_in_construction, NULL);
 
   if (CLASS_HAS_PROPS (class))
     {
@@ -1845,14 +1834,14 @@ g_object_newv (GType       object_type,
 
           if G_UNLIKELY (!pspec)
             {
-              g_critical ("%s: object class `%s' has no property named `%s'",
+              g_critical ("%s: object class '%s' has no property named '%s'",
                           G_STRFUNC, g_type_name (object_type), parameters[i].name);
               continue;
             }
 
           if G_UNLIKELY (~pspec->flags & G_PARAM_WRITABLE)
             {
-              g_critical ("%s: property `%s' of object class `%s' is not writable",
+              g_critical ("%s: property '%s' of object class '%s' is not writable",
                           G_STRFUNC, pspec->name, g_type_name (object_type));
               continue;
             }
@@ -1864,7 +1853,7 @@ g_object_newv (GType       object_type,
                     break;
               if G_UNLIKELY (k != j)
                 {
-                  g_critical ("%s: construct property `%s' for type `%s' cannot be set twice",
+                  g_critical ("%s: construct property '%s' for type '%s' cannot be set twice",
                               G_STRFUNC, parameters[i].name, g_type_name (object_type));
                   continue;
                 }
@@ -1939,7 +1928,7 @@ g_object_new_valist (GType        object_type,
 
           if G_UNLIKELY (!pspec)
             {
-              g_critical ("%s: object class `%s' has no property named `%s'",
+              g_critical ("%s: object class '%s' has no property named '%s'",
                           G_STRFUNC, g_type_name (object_type), name);
               /* Can't continue because arg list will be out of sync. */
               break;
@@ -1947,7 +1936,7 @@ g_object_new_valist (GType        object_type,
 
           if G_UNLIKELY (~pspec->flags & G_PARAM_WRITABLE)
             {
-              g_critical ("%s: property `%s' of object class `%s' is not writable",
+              g_critical ("%s: property '%s' of object class '%s' is not writable",
                           G_STRFUNC, pspec->name, g_type_name (object_type));
               break;
             }
@@ -1959,7 +1948,7 @@ g_object_new_valist (GType        object_type,
                     break;
               if G_UNLIKELY (i != n_params)
                 {
-                  g_critical ("%s: property `%s' for type `%s' cannot be set twice",
+                  g_critical ("%s: property '%s' for type '%s' cannot be set twice",
                               G_STRFUNC, name, g_type_name (object_type));
                   break;
                 }
@@ -2084,7 +2073,7 @@ g_object_set_valist (GObject       *object,
                                        TRUE);
       if (!pspec)
        {
-         g_warning ("%s: object class `%s' has no property named `%s'",
+         g_warning ("%s: object class '%s' has no property named '%s'",
                     G_STRFUNC,
                     G_OBJECT_TYPE_NAME (object),
                     name);
@@ -2092,15 +2081,15 @@ g_object_set_valist (GObject     *object,
        }
       if (!(pspec->flags & G_PARAM_WRITABLE))
        {
-         g_warning ("%s: property `%s' of object class `%s' is not writable",
+         g_warning ("%s: property '%s' of object class '%s' is not writable",
                     G_STRFUNC,
                     pspec->name,
                     G_OBJECT_TYPE_NAME (object));
          break;
        }
-      if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction_list (object))
+      if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction (object))
         {
-          g_warning ("%s: construct property \"%s\" for object `%s' can't be set after construction",
+          g_warning ("%s: construct property \"%s\" for object '%s' can't be set after construction",
                      G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
           break;
         }
@@ -2165,7 +2154,7 @@ g_object_get_valist (GObject       *object,
                                        TRUE);
       if (!pspec)
        {
-         g_warning ("%s: object class `%s' has no property named `%s'",
+         g_warning ("%s: object class '%s' has no property named '%s'",
                     G_STRFUNC,
                     G_OBJECT_TYPE_NAME (object),
                     name);
@@ -2173,7 +2162,7 @@ g_object_get_valist (GObject       *object,
        }
       if (!(pspec->flags & G_PARAM_READABLE))
        {
-         g_warning ("%s: property `%s' of object class `%s' is not readable",
+         g_warning ("%s: property '%s' of object class '%s' is not readable",
                     G_STRFUNC,
                     pspec->name,
                     G_OBJECT_TYPE_NAME (object));
@@ -2209,6 +2198,10 @@ g_object_get_valist (GObject      *object,
  *  name/value pairs, followed by %NULL
  *
  * Sets properties on an object.
+ *
+ * Note that the "notify" signals are queued and only emitted (in
+ * reverse order) after all properties have been set. See
+ * g_object_freeze_notify().
  */
 void
 g_object_set (gpointer     _object,
@@ -2304,17 +2297,17 @@ g_object_set_property (GObject      *object,
                                    G_OBJECT_TYPE (object),
                                    TRUE);
   if (!pspec)
-    g_warning ("%s: object class `%s' has no property named `%s'",
+    g_warning ("%s: object class '%s' has no property named '%s'",
               G_STRFUNC,
               G_OBJECT_TYPE_NAME (object),
               property_name);
   else if (!(pspec->flags & G_PARAM_WRITABLE))
-    g_warning ("%s: property `%s' of object class `%s' is not writable",
+    g_warning ("%s: property '%s' of object class '%s' is not writable",
                G_STRFUNC,
                pspec->name,
                G_OBJECT_TYPE_NAME (object));
-  else if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction_list (object))
-    g_warning ("%s: construct property \"%s\" for object `%s' can't be set after construction",
+  else if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction (object))
+    g_warning ("%s: construct property \"%s\" for object '%s' can't be set after construction",
                G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
   else
     object_set_property (object, pspec, value, nqueue);
@@ -2357,12 +2350,12 @@ g_object_get_property (GObject     *object,
                                    G_OBJECT_TYPE (object),
                                    TRUE);
   if (!pspec)
-    g_warning ("%s: object class `%s' has no property named `%s'",
+    g_warning ("%s: object class '%s' has no property named '%s'",
               G_STRFUNC,
               G_OBJECT_TYPE_NAME (object),
               property_name);
   else if (!(pspec->flags & G_PARAM_READABLE))
-    g_warning ("%s: property `%s' of object class `%s' is not readable",
+    g_warning ("%s: property '%s' of object class '%s' is not readable",
                G_STRFUNC,
                pspec->name,
                G_OBJECT_TYPE_NAME (object));
@@ -2379,7 +2372,7 @@ g_object_get_property (GObject       *object,
        }
       else if (!g_value_type_transformable (pspec->value_type, G_VALUE_TYPE (value)))
        {
-         g_warning ("%s: can't retrieve property `%s' of type `%s' as value of type `%s'",
+         g_warning ("%s: can't retrieve property '%s' of type '%s' as value of type '%s'",
                     G_STRFUNC, pspec->name,
                     g_type_name (pspec->value_type),
                     G_VALUE_TYPE_NAME (value));
@@ -3049,12 +3042,6 @@ g_object_ref (gpointer _object)
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
   g_return_val_if_fail (object->ref_count > 0, NULL);
   
-#ifdef  G_ENABLE_DEBUG
-  if (g_trap_object_ref == object)
-    G_BREAKPOINT ();
-#endif  /* G_ENABLE_DEBUG */
-
-
   old_val = g_atomic_int_add (&object->ref_count, 1);
 
   if (old_val == 1 && OBJECT_HAS_TOGGLE_REF (object))
@@ -3081,11 +3068,6 @@ g_object_unref (gpointer _object)
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (object->ref_count > 0);
   
-#ifdef  G_ENABLE_DEBUG
-  if (g_trap_object_ref == object)
-    G_BREAKPOINT ();
-#endif  /* G_ENABLE_DEBUG */
-
   /* here we want to atomically do: if (ref_count>1) { ref_count--; return; } */
  retry_atomic_decrement1:
   old_ref = g_atomic_int_get (&object->ref_count);
@@ -3335,7 +3317,7 @@ g_object_dup_qdata (GObject        *object,
  *
  * If the previous value was replaced then ownership of the
  * old value (@oldval) is passed to the caller, including
- * the registred destroy notify for it (passed out in @old_destroy).
+ * the registered destroy notify for it (passed out in @old_destroy).
  * Its up to the caller to free this as he wishes, which may
  * or may not include using @old_destroy as sometimes replacement
  * should not destroy the object in the normal way.
@@ -3544,7 +3526,7 @@ g_object_dup_data (GObject        *object,
  *
  * If the previous value was replaced then ownership of the
  * old value (@oldval) is passed to the caller, including
- * the registred destroy notify for it (passed out in @old_destroy).
+ * the registered destroy notify for it (passed out in @old_destroy).
  * Its up to the caller to free this as he wishes, which may
  * or may not include using @old_destroy as sometimes replacement
  * should not destroy the object in the normal way.
@@ -3671,14 +3653,14 @@ g_value_object_collect_value (GValue      *value,
       GObject *object = collect_values[0].v_pointer;
       
       if (object->g_type_instance.g_class == NULL)
-       return g_strconcat ("invalid unclassed object pointer for value type `",
+       return g_strconcat ("invalid unclassed object pointer for value type '",
                            G_VALUE_TYPE_NAME (value),
                            "'",
                            NULL);
       else if (!g_value_type_compatible (G_OBJECT_TYPE (object), G_VALUE_TYPE (value)))
-       return g_strconcat ("invalid object type `",
+       return g_strconcat ("invalid object type '",
                            G_OBJECT_TYPE_NAME (object),
-                           "' for value type `",
+                           "' for value type '",
                            G_VALUE_TYPE_NAME (value),
                            "'",
                            NULL);
@@ -3700,7 +3682,7 @@ g_value_object_lcopy_value (const GValue *value,
   GObject **object_p = collect_values[0].v_pointer;
   
   if (!object_p)
-    return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+    return g_strdup_printf ("value location for '%s' passed as NULL", G_VALUE_TYPE_NAME (value));
 
   if (!value->data[0].v_pointer)
     *object_p = NULL;