diff options
author | Emmanuele Bassi <ebassi@linux.intel.com> | 2011-08-18 11:27:24 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@linux.intel.com> | 2011-08-19 15:31:14 +0100 |
commit | 42e79ad6fb4e23be31714559f34e2d679691a0f7 (patch) | |
tree | 91b309f65a825520365c7a5f8fd220564466f856 /gobject/gproperty.c | |
parent | 5b542fb90afef84bb8e2d1b0507f87417070e080 (diff) | |
download | glib-g-property.tar.gz |
gproperty: Allow control over the accessors copy semanticsg-property
It should be possible to define whether a property will take a
reference, or make a copy, of the value being set or retrieved,
so that we can reflect this behaviour inside the introspection
and documentation.
In order to do that, we can add two new flags to GProperty, detailing
the behaviour for setter and getter separately (and a simple shorthand
for both).
By default, GProperty will now not copy a boxed type, or take a
reference on an object type, when setting a new value; it is up
to the developer to specify this behaviour.
Diffstat (limited to 'gobject/gproperty.c')
-rw-r--r-- | gobject/gproperty.c | 153 |
1 files changed, 118 insertions, 35 deletions
diff --git a/gobject/gproperty.c b/gobject/gproperty.c index b94b62b3e..89ff1d5f7 100644 --- a/gobject/gproperty.c +++ b/gobject/gproperty.c @@ -156,11 +156,18 @@ * ]| * <para>Note that calling g_property_set() for a property holding a * complex type (e.g. #GObject or #GBoxed) without a specific setter - * function will result in the value being copied in the private data - * structure's field. In contrast, calling g_property_get() will return - * a pointer to the private data structure's field: it is up to the - * getter function to decide whether to return a copy of the internal - * data or the pointer itself.</para> + * function will, by default, result in the pointer to the new value + * being copied in the private data structure's field; if you need to + * copy a boxed type, or take a reference on an object type, you will + * need to set the %G_PROPERTY_COPY_SET flag when creating the + * property.</para> + * + * <para>Calling g_property_get() will return a pointer to the private + * data structure's field, unless %G_PROPERTY_COPY_GET is set when + * creating the property, in which case the returned value will either + * be a copy of the private data structure field if it is a boxed type + * or the instance with its reference count increased if it is an object + * type.</para> * </refsect3> * * <refsect3> @@ -363,7 +370,7 @@ * * |[ * test_object_property[PROP_WIDTH] = - * g_int_property_new ("width", G_PROPERTY_READWRITE, + * g_int_property_new ("width", G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET, * G_STRUCT_OFFSET (TestObjectPrivate, width), * test_object_set_width, /* explicit setter */ * NULL /* implicit getter */); @@ -432,7 +439,7 @@ * |[ * G_DEFINE_PROPERTY_GET (TestObject, test_object, int, width) * G_DEFINE_PROPERTY_SET_WITH_CODE (Test_object, test_object, int, width, - * test_object_queue_resize (self)) + * test_object_queue_action (self)) * ]| * * <para>The WITH_CODE variant of the setter will define the "self" and @@ -2405,8 +2412,13 @@ g_string_property_set_value (GProperty *property, return FALSE; } - g_free (str); - (* (gpointer *) field_p) = g_strdup (value); + if (property->flags & G_PROPERTY_COPY_SET) + { + g_free (str); + (* (gpointer *) field_p) = g_strdup (value); + } + else + (* (gpointer *) field_p) = (gpointer) value; property_unlock_internal (property, gobject); @@ -2446,7 +2458,10 @@ g_string_property_get_value (GProperty *property, priv_p = get_private_pointer (gobject, property->priv_offset); field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset); - retval = (* (gpointer *) field_p); + if (property->flags & G_PROPERTY_COPY_GET) + retval = g_strdup ((* (gpointer *) field_p)); + else + retval = (* (gpointer *) field_p); return retval; } @@ -2612,15 +2627,20 @@ g_boxed_property_set_value (GProperty *property, priv_p = get_private_pointer (gobject, property->priv_offset); field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset); - old_value = (* (gpointer *) field_p); + if (property->flags & G_PROPERTY_COPY_SET) + { + old_value = (* (gpointer *) field_p); - if (value != NULL) - (* (gpointer *) field_p) = g_boxed_copy (((GParamSpec *) property)->value_type, value); - else - (* (gpointer *) field_p) = NULL; + if (value != NULL) + (* (gpointer *) field_p) = g_boxed_copy (((GParamSpec *) property)->value_type, value); + else + (* (gpointer *) field_p) = NULL; - if (old_value != NULL) - g_boxed_free (((GParamSpec *) property)->value_type, old_value); + if (old_value != NULL) + g_boxed_free (((GParamSpec *) property)->value_type, old_value); + } + else + (* (gpointer *) field_p) = value; property_unlock_internal (property, gobject); @@ -2659,7 +2679,11 @@ g_boxed_property_get_value (GProperty *property, priv_p = get_private_pointer (gobject, property->priv_offset); field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset); - value = (* (gpointer *) field_p); + + if (property->flags & G_PROPERTY_COPY_GET) + value = g_boxed_copy (((GParamSpec *) property)->value_type, (* (gpointer *) field_p)); + else + value = (* (gpointer *) field_p); return value; } @@ -2836,19 +2860,24 @@ g_object_property_set_value (GProperty *property, return FALSE; } - obj = (* (gpointer *) field_p); - if (obj != NULL) - g_object_unref (obj); - - (* (gpointer *) field_p) = obj = value; - - if (obj != NULL) + if (property->flags & G_PROPERTY_COPY_SET) { - if (G_IS_INITIALLY_UNOWNED (obj)) - g_object_ref_sink (obj); - else - g_object_ref (obj); + obj = (* (gpointer *) field_p); + if (obj != NULL) + g_object_unref (obj); + + (* (gpointer *) field_p) = obj = value; + + if (obj != NULL) + { + if (G_IS_INITIALLY_UNOWNED (obj)) + g_object_ref_sink (obj); + else + g_object_ref (obj); + } } + else + (* (gpointer *) field_p) = value; property_unlock_internal (property, gobject); @@ -2887,7 +2916,17 @@ g_object_property_get_value (GProperty *property, priv_p = g_type_instance_get_private (gobject, G_OBJECT_TYPE (gobject)); field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset); - return (* (gpointer *) field_p); + if (property->flags & G_PROPERTY_COPY_GET) + { + gpointer value = (* (gpointer *) field_p); + + if (value != NULL) + return g_object_ref (value); + else + return NULL; + } + else + return (* (gpointer *) field_p); } else { @@ -4558,8 +4597,11 @@ g_property_get_valist (GProperty *property, value = g_string_property_get_value (property, gobject); - if ((flags & G_PROPERTY_COLLECT_COPY) != 0) - (* (gchar **) ret_p) = g_strdup (value); + if (((flags & G_PROPERTY_COLLECT_COPY) != 0) && + (property->flags & G_PROPERTY_COPY_GET) == 0) + { + (* (gchar **) ret_p) = g_strdup (value); + } else (* (gconstpointer *) ret_p) = value; } @@ -4571,7 +4613,8 @@ g_property_get_valist (GProperty *property, boxed = g_boxed_property_get_value (property, gobject); - if ((flags & G_PROPERTY_COLLECT_COPY) != 0) + if (((flags & G_PROPERTY_COLLECT_COPY) != 0) && + (property->flags & G_PROPERTY_COPY_GET) == 0) { if (boxed != NULL) (* (gpointer *) ret_p) = g_boxed_copy (gtype, boxed); @@ -4587,8 +4630,12 @@ g_property_get_valist (GProperty *property, { gpointer obj = g_object_property_get_value (property, gobject); - if (((flags & G_PROPERTY_COLLECT_REF) != 0) && obj != NULL) - (* (gpointer *) ret_p) = g_object_ref (obj); + if ((((flags & G_PROPERTY_COLLECT_REF) != 0) && + (property->flags & G_PROPERTY_COPY_GET) == 0) && + (obj != NULL)) + { + (* (gpointer *) ret_p) = g_object_ref (obj); + } else (* (gpointer *) ret_p) = obj; } @@ -5349,6 +5396,42 @@ g_property_is_atomic (GProperty *property) } /** + * g_property_is_copy_set: + * @property: a #GProperty + * + * Checks whether the @property has the %G_PROPERTY_COPY_SET flag set. + * + * Return value: %TRUE if the flag is set, and %FALSE otherwise + * + * Since: 2.30 + */ +gboolean +g_property_is_copy_set (GProperty *property) +{ + g_return_val_if_fail (G_IS_PROPERTY (property), FALSE); + + return (property->flags & G_PROPERTY_COPY_SET) != 0; +} + +/** + * g_property_is_copy_get: + * @property: a #GProperty + * + * Checks whether the @property has the %G_PROPERTY_COPY_GET flag set. + * + * Return value: %TRUE if the flag is set, and %FALSE otherwise + * + * Since: 2.30 + */ +gboolean +g_property_is_copy_get (GProperty *property) +{ + g_return_val_if_fail (G_IS_PROPERTY (property), FALSE); + + return (property->flags & G_PROPERTY_COPY_GET) != 0; +} + +/** * g_property_lock: * @property: a #GProperty * @gobject: a #GObject |