X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gobject%2Fgobject.c;h=cd00244f630c075bece552167b7bb2ea35562749;hb=9da85c7262325478e8730ae9f3e76bd0528a9a8c;hp=2a88313779cf0c999b61010cc7a97887291adc51;hpb=323242578524a1b6355d8451015b14ca75aa0afa;p=platform%2Fupstream%2Fglib.git
diff --git a/gobject/gobject.c b/gobject/gobject.c
index 2a88313..cd00244 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -43,10 +43,10 @@
* methods for all object types in GTK+, Pango and other libraries
* based on GObject. The GObject class provides methods for object
* construction and destruction, property access methods, and signal
- * support. Signals are described in detail in .
+ * support. Signals are described in detail [here][gobject-Signals].
+ *
+ * ## Floating references # {#floating-ref}
*
- *
* GInitiallyUnowned is derived from GObject. The only difference between
* the two is that the initial reference of a GInitiallyUnowned is flagged
* as a "floating" reference. This means that it is not specifically
@@ -78,23 +78,24 @@
* language bindings that provide automated reference and memory ownership
* maintenance (such as smart pointers or garbage collection) should not
* expose floating references in their API.
- *
*
* Some object implementations may need to save an objects floating state
* across certain code portions (an example is #GtkMenu), to achieve this,
* the following sequence can be used:
*
* |[
- * /* save floating state */
+ * // save floating state
* gboolean was_floating = g_object_is_floating (object);
* g_object_ref_sink (object);
- * /* protected code portion */
- * ...;
- * /* restore floating state */
+ * // protected code portion
+ *
+ * ...
+ *
+ * // restore floating state
* if (was_floating)
* g_object_force_floating (object);
* else
- * g_object_unref (object); /* release previously acquired reference */
+ * g_object_unref (object); // release previously acquired reference
* ]|
*/
@@ -479,7 +480,7 @@ g_object_do_class_init (GObjectClass *class)
* text_view)
* ]|
* It is important to note that you must use
- * canonical parameter names as
+ * [canonical][canonical-parameter-name] parameter names as
* detail strings for the notify signal.
*/
gobject_signals[NOTIFY] =
@@ -522,7 +523,12 @@ install_property_internal (GType g_type,
* @property_id: the id for the new property
* @pspec: the #GParamSpec for the new property
*
- * Installs a new property. This is usually done in the class initializer.
+ * Installs a new property.
+ *
+ * All properties should be installed during the class initializer. It
+ * is possible to install properties after that, but doing so is not
+ * recommend, and specifically, is not guaranteed to be thread-safe vs.
+ * use of properties on the same type on other threads.
*
* Note that it is possible to redefine a property in a derived class,
* by installing a property with the same name. This can be useful at times,
@@ -539,9 +545,6 @@ g_object_class_install_property (GObjectClass *class,
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);
- 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;
g_return_if_fail (pspec->flags & (G_PARAM_READABLE | G_PARAM_WRITABLE));
@@ -576,8 +579,12 @@ g_object_class_install_property (GObjectClass *class,
* @pspecs: (array length=n_pspecs): the #GParamSpecs array
* defining the new properties
*
- * Installs new properties from an array of #GParamSpecs. This is
- * usually done in the class initializer.
+ * Installs new properties from an array of #GParamSpecs.
+ *
+ * All properties should be installed during the class initializer. It
+ * is possible to install properties after that, but doing so is not
+ * recommend, and specifically, is not guaranteed to be thread-safe vs.
+ * use of properties on the same type on other threads.
*
* The property id of each property is the index of each #GParamSpec in
* the @pspecs array.
@@ -652,9 +659,6 @@ 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);
@@ -1022,8 +1026,8 @@ 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_critical ("object %s %p finalized while still in-construction",
+ G_OBJECT_TYPE_NAME (object), object);
}
g_datalist_clear (&object->qdata);
@@ -1291,6 +1295,56 @@ g_object_thaw_notify (GObject *object)
g_object_unref (object);
}
+static void
+consider_issuing_property_deprecation_warning (const GParamSpec *pspec)
+{
+ static GHashTable *already_warned_table;
+ static const gchar *enable_diagnostic;
+ static GMutex already_warned_lock;
+ gboolean already;
+
+ if (!(pspec->flags & G_PARAM_DEPRECATED))
+ return;
+
+ if (g_once_init_enter (&enable_diagnostic))
+ {
+ const gchar *value = g_getenv ("G_ENABLE_DIAGNOSTIC");
+
+ if (!value)
+ value = "-";
+
+ g_once_init_leave (&enable_diagnostic, value);
+ }
+
+ if (enable_diagnostic[0] == '0')
+ return;
+
+ /* We hash only on property names: this means that we could end up in
+ * a situation where we fail to emit a warning about a pair of
+ * same-named deprecated properties used on two separate types.
+ * That's pretty unlikely to occur, and even if it does, you'll still
+ * have seen the warning for the first one...
+ *
+ * Doing it this way lets us hash directly on the (interned) property
+ * name pointers.
+ */
+ g_mutex_lock (&already_warned_lock);
+
+ if (already_warned_table == NULL)
+ already_warned_table = g_hash_table_new (NULL, NULL);
+
+ already = g_hash_table_contains (already_warned_table, (gpointer) pspec->name);
+ if (!already)
+ g_hash_table_add (already_warned_table, (gpointer) pspec->name);
+
+ g_mutex_unlock (&already_warned_lock);
+
+ if (!already)
+ g_warning ("The property %s:%s is deprecated and shouldn't be used "
+ "anymore. It will be removed in a future version.",
+ g_type_name (pspec->owner_type), pspec->name);
+}
+
static inline void
object_get_property (GObject *object,
GParamSpec *pspec,
@@ -1309,8 +1363,10 @@ object_get_property (GObject *object,
redirect = g_param_spec_get_redirect_target (pspec);
if (redirect)
- pspec = redirect;
-
+ pspec = redirect;
+
+ consider_issuing_property_deprecation_warning (pspec);
+
class->get_property (object, param_id, value, pspec);
}
@@ -1324,7 +1380,6 @@ object_set_property (GObject *object,
GObjectClass *class = g_type_class_peek (pspec->owner_type);
guint param_id = PARAM_SPEC_PARAM_ID (pspec);
GParamSpec *redirect;
- static const gchar * enable_diagnostic = NULL;
if (class == NULL)
{
@@ -1337,21 +1392,6 @@ object_set_property (GObject *object,
if (redirect)
pspec = redirect;
- if (G_UNLIKELY (!enable_diagnostic))
- {
- enable_diagnostic = g_getenv ("G_ENABLE_DIAGNOSTIC");
- if (!enable_diagnostic)
- enable_diagnostic = "0";
- }
-
- if (enable_diagnostic[0] == '1')
- {
- if (pspec->flags & G_PARAM_DEPRECATED)
- g_warning ("The property %s:%s is deprecated and shouldn't be used "
- "anymore. It will be removed in a future version.",
- G_OBJECT_TYPE_NAME (object), pspec->name);
- }
-
/* 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))
@@ -1372,14 +1412,17 @@ object_set_property (GObject *object,
}
else
{
- GParamSpec *notify_pspec;
-
class->set_property (object, param_id, &tmp_value, pspec);
- notify_pspec = get_notify_pspec (pspec);
+ if (~pspec->flags & G_PARAM_EXPLICIT_NOTIFY)
+ {
+ GParamSpec *notify_pspec;
+
+ notify_pspec = get_notify_pspec (pspec);
- if (notify_pspec != NULL)
- g_object_notify_queue_add (object, nqueue, notify_pspec);
+ if (notify_pspec != NULL)
+ g_object_notify_queue_add (object, nqueue, notify_pspec);
+ }
}
g_value_unset (&tmp_value);
}
@@ -1396,9 +1439,12 @@ object_interface_check_properties (gpointer check_data,
class = g_type_class_ref (iface_class->g_instance_type);
- if (!G_IS_OBJECT_CLASS (class))
+ if (class == NULL)
return;
+ if (!G_IS_OBJECT_CLASS (class))
+ goto out;
+
pspecs = g_param_spec_pool_list (pspec_pool, iface_type, &n);
while (n--)
@@ -1529,6 +1575,7 @@ object_interface_check_properties (gpointer check_data,
g_free (pspecs);
+ out:
g_type_class_unref (class);
}
@@ -1624,6 +1671,7 @@ g_object_new_with_custom_constructor (GObjectClass *class,
for (j = 0; j < n_params; j++)
if (params[j].pspec == pspec)
{
+ consider_issuing_property_deprecation_warning (pspec);
value = params[j].value;
break;
}
@@ -1700,7 +1748,10 @@ g_object_new_with_custom_constructor (GObjectClass *class,
/* set remaining properties */
for (i = 0; i < n_params; i++)
if (!(params[i].pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)))
- object_set_property (object, params[i].pspec, params[i].value, nqueue);
+ {
+ consider_issuing_property_deprecation_warning (params[i].pspec);
+ object_set_property (object, params[i].pspec, params[i].value, nqueue);
+ }
/* If nqueue is non-NULL then we are frozen. Thaw it. */
if (nqueue)
@@ -1746,6 +1797,7 @@ g_object_new_internal (GObjectClass *class,
for (j = 0; j < n_params; j++)
if (params[j].pspec == pspec)
{
+ consider_issuing_property_deprecation_warning (pspec);
value = params[j].value;
break;
}
@@ -1771,7 +1823,10 @@ g_object_new_internal (GObjectClass *class,
*/
for (i = 0; i < n_params; i++)
if (!(params[i].pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)))
- object_set_property (object, params[i].pspec, params[i].value, nqueue);
+ {
+ consider_issuing_property_deprecation_warning (params[i].pspec);
+ object_set_property (object, params[i].pspec, params[i].value, nqueue);
+ }
g_object_notify_queue_thaw (object, nqueue);
}
@@ -2099,10 +2154,11 @@ g_object_set_valist (GObject *object,
g_value_unset (&value);
break;
}
-
+
+ consider_issuing_property_deprecation_warning (pspec);
object_set_property (object, pspec, &value, nqueue);
g_value_unset (&value);
-
+
name = va_arg (var_args, gchar*);
}
@@ -2240,7 +2296,7 @@ g_object_set (gpointer _object,
* "obj-property", &objval,
* NULL);
*
- * /* Do something with intval, strval, objval */
+ * // Do something with intval, strval, objval
*
* g_free (strval);
* g_object_unref (objval);
@@ -2302,8 +2358,11 @@ g_object_set_property (GObject *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);
-
+ {
+ consider_issuing_property_deprecation_warning (pspec);
+ object_set_property (object, pspec, value, nqueue);
+ }
+
g_object_notify_queue_thaw (object, nqueue);
g_object_unref (object);
}
@@ -2739,8 +2798,7 @@ object_floating_flag_handler (GObject *object,
* g_object_is_floating:
* @object: (type GObject.Object): a #GObject
*
- * Checks whether @object has a floating
- * reference.
+ * Checks whether @object has a [floating][floating-ref] reference.
*
* Since: 2.10
*
@@ -2759,8 +2817,7 @@ g_object_is_floating (gpointer _object)
* @object: (type GObject.Object): a #GObject
*
* Increase the reference count of @object, and possibly remove the
- * floating reference, if @object
- * has a floating reference.
+ * [floating][floating-ref] reference, if @object has a floating reference.
*
* In other words, if the object is floating, then this call "assumes
* ownership" of the floating reference, converting it to a normal
@@ -2790,11 +2847,10 @@ g_object_ref_sink (gpointer _object)
* g_object_force_floating:
* @object: a #GObject
*
- * This function is intended for #GObject implementations to re-enforce a
- * floating object reference.
- * Doing this is seldom required: all
- * #GInitiallyUnowneds are created with a floating reference which
- * usually just needs to be sunken by calling g_object_ref_sink().
+ * This function is intended for #GObject implementations to re-enforce
+ * a [floating][floating-ref] object reference. Doing this is seldom
+ * required: all #GInitiallyUnowneds are created with a floating reference
+ * which usually just needs to be sunken by calling g_object_ref_sink().
*
* Since: 2.10
*/
@@ -3141,9 +3197,6 @@ g_object_unref (gpointer _object)
* Otherwise, the reference count of the object is decreased and the
* pointer is set to %NULL.
*
- * This function is threadsafe and modifies the pointer atomically,
- * using memory barriers where needed.
- *
* A macro is also included that allows this function to be used without
* pointer casts.
*
@@ -3265,7 +3318,7 @@ g_object_dup_qdata (GObject *object,
* or may not include using @old_destroy as sometimes replacement
* should not destroy the object in the normal way.
*
- * Return: %TRUE if the existing value for @quark was replaced
+ * Returns: %TRUE if the existing value for @quark was replaced
* by @newval, %FALSE otherwise.
*
* Since: 2.34
@@ -3474,7 +3527,7 @@ g_object_dup_data (GObject *object,
* or may not include using @old_destroy as sometimes replacement
* should not destroy the object in the normal way.
*
- * Return: %TRUE if the existing value for @key was replaced
+ * Returns: %TRUE if the existing value for @key was replaced
* by @newval, %FALSE otherwise.
*
* Since: 2.34