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