[glib/g-property: 9/26] gproperty: Clarify handling of complex types
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/g-property: 9/26] gproperty: Clarify handling of complex types
- Date: Wed, 17 Aug 2011 13:59:29 +0000 (UTC)
commit 5f052c7212cdf2cd187026d38fab80308e8341c6
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Mon Jun 6 14:26:14 2011 +0100
gproperty: Clarify handling of complex types
The GProperty setters and getters deal with pointers; for complex types,
a copy of the content will be made - but g_property_get() will return a
pointer and leave the memory management decision to the implementation
of the public-facing getter function.
This change means that the GPropertyBoxedSet and GPropertyBoxedGet must
return gpointer, not gconstpointer, to leave the chance of using
refcounted boxed types up to the caller and implementation.
The autoproperties test has been amended to cope with both cases, and
verify the default implementation.
gobject/gproperty.c | 50 +++++++++++++----------
gobject/gproperty.h | 4 +-
gobject/tests/autoproperties.c | 87 ++++++++++++++++++++++++++++++----------
3 files changed, 96 insertions(+), 45 deletions(-)
---
diff --git a/gobject/gproperty.c b/gobject/gproperty.c
index 69d5500..69e5a5e 100644
--- a/gobject/gproperty.c
+++ b/gobject/gproperty.c
@@ -38,7 +38,8 @@
* pointer to the private data structure as its last member, e.g.:
*
* |[
- * typedef struct _TestObject TestObject;
+ * typedef struct _TestObject TestObject;
+ * typedef struct _TestObjectPrivate TestObjectPrivate;
*
* struct _TestObject
* {
@@ -64,7 +65,8 @@
*
* |[
* /* the private data structure */
- * struct _TestObjectPrivate {
+ * struct _TestObjectPrivate
+ * {
* int x;
* int y;
* int width;
@@ -152,6 +154,13 @@
* return retval;
* }
* ]|
+ * <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>
* </refsect3>
*
* <refsect3>
@@ -2520,9 +2529,9 @@ g_boxed_property_validate (GProperty *property,
}
static inline gboolean
-g_boxed_property_set_value (GProperty *property,
- gpointer gobject,
- gconstpointer value)
+g_boxed_property_set_value (GProperty *property,
+ gpointer gobject,
+ gpointer value)
{
gboolean retval = FALSE;
@@ -2552,29 +2561,26 @@ g_boxed_property_set_value (GProperty *property,
retval = TRUE;
}
- if (property->field_offset >= 0)
+ else if (property->field_offset >= 0)
{
gpointer priv_p, field_p;
+ gpointer old_value;
property_lock_internal (property, gobject);
priv_p = get_private_pointer (gobject, property->priv_offset);
field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset);
- if ((* (gpointer *) field_p) == value)
- {
- property_unlock_internal (property, gobject);
- return FALSE;
- }
-
- if ((* (gpointer *) field_p) != NULL)
- g_boxed_free (((GParamSpec *) property)->value_type, (* (gpointer *) field_p));
+ 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 (old_value != NULL)
+ g_boxed_free (((GParamSpec *) property)->value_type, old_value);
+
property_unlock_internal (property, gobject);
g_object_notify_by_pspec (gobject, (GParamSpec *) property);
@@ -2589,7 +2595,7 @@ g_boxed_property_set_value (GProperty *property,
return retval;
}
-static inline gconstpointer
+static inline gpointer
g_boxed_property_get_value (GProperty *property,
gpointer gobject)
{
@@ -2605,14 +2611,16 @@ g_boxed_property_get_value (GProperty *property,
{
return ((GBoxedProperty *) property)->getter (gobject);
}
- if (property->field_offset >= 0)
+ else if (property->field_offset >= 0)
{
gpointer priv_p, field_p;
+ gpointer value;
priv_p = get_private_pointer (gobject, property->priv_offset);
field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset);
+ value = (* (gpointer *) field_p);
- return (* (gpointer *) field_p);
+ return value;
}
else
{
@@ -4423,7 +4431,7 @@ g_property_get_valist (GProperty *property,
break;
case G_TYPE_BOXED:
- (* (gconstpointer *) ret_p) = g_boxed_property_get_value (property, gobject);
+ (* (gpointer *) ret_p) = g_boxed_property_get_value (property, gobject);
break;
case G_TYPE_OBJECT:
@@ -4850,10 +4858,10 @@ g_property_lcopy (GProperty *property,
if ((flags & G_PROPERTY_COLLECT_COPY) != 0)
{
- if (boxed == NULL)
- (* (gpointer *) _cvalue->v_pointer) = NULL;
- else
+ if (boxed != NULL)
(* (gpointer *) _cvalue->v_pointer) = g_boxed_copy (gtype, boxed);
+ else
+ (* (gpointer *) _cvalue->v_pointer) = NULL;
}
else
(* (gpointer *) _cvalue->v_pointer) = (gpointer) boxed;
diff --git a/gobject/gproperty.h b/gobject/gproperty.h
index 41427f7..9b4e4ed 100644
--- a/gobject/gproperty.h
+++ b/gobject/gproperty.h
@@ -254,8 +254,8 @@ typedef void (* GPropertyStringSet) (gpointer gobject,
typedef const gchar * (* GPropertyStringGet) (gpointer gobject);
typedef void (* GPropertyBoxedSet) (gpointer gobject,
- gconstpointer value);
-typedef gconstpointer (* GPropertyBoxedGet) (gpointer gobject);
+ gpointer value);
+typedef gpointer (* GPropertyBoxedGet) (gpointer gobject);
typedef void (* GPropertyObjectSet) (gpointer gobject,
gpointer value);
diff --git a/gobject/tests/autoproperties.c b/gobject/tests/autoproperties.c
index 7eac768..2f2127b 100644
--- a/gobject/tests/autoproperties.c
+++ b/gobject/tests/autoproperties.c
@@ -122,6 +122,23 @@ test_flags_value_get_type (void)
return g_define_type_id__volatile;
}
+static TestBoxed *
+test_boxed_new (int x,
+ int y,
+ int width,
+ int height)
+{
+ TestBoxed *retval = g_new (TestBoxed, 1);
+
+ retval->x = x;
+ retval->y = y;
+ retval->width = width;
+ retval->height = height;
+ retval->ref_count = 1;
+
+ return retval;
+}
+
static gpointer
test_boxed_copy (gpointer data)
{
@@ -129,6 +146,12 @@ test_boxed_copy (gpointer data)
{
TestBoxed *boxed = data;
+ if (g_test_verbose ())
+ g_print ("*** copy of boxed %p (ref count: %d) ***\n", boxed, boxed->ref_count);
+
+ if (boxed->ref_count < 0)
+ return test_boxed_new (boxed->x, boxed->y, boxed->width, boxed->height);
+
boxed->ref_count += 1;
}
@@ -142,6 +165,12 @@ test_boxed_free (gpointer data)
{
TestBoxed *boxed = data;
+ if (g_test_verbose ())
+ g_print ("*** free of boxed %p (ref count: %d) ***\n", boxed, boxed->ref_count);
+
+ if (boxed->ref_count < 0)
+ return;
+
boxed->ref_count -= 1;
if (boxed->ref_count == 0)
@@ -149,22 +178,7 @@ test_boxed_free (gpointer data)
}
}
-GType
-test_boxed_get_type (void)
-{
- static volatile gsize g_define_type_id__volatile = 0;
-
- if (g_once_init_enter (&g_define_type_id__volatile))
- {
- GType g_define_type_id =
- g_boxed_type_register_static (g_intern_static_string ("TestBoxed"),
- test_boxed_copy,
- test_boxed_free);
- g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
- }
-
- return g_define_type_id__volatile;
-}
+G_DEFINE_BOXED_TYPE (TestBoxed, test_boxed, test_boxed_copy, test_boxed_free)
static GParamSpec *test_object_properties[LAST_PROP] = { NULL, };
@@ -180,7 +194,23 @@ G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, float, width)
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, double, x_align)
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, TestEnumValue, enum_value)
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, TestFlagsValue, flags_value)
-G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, const TestBoxed *, boxed)
+
+G_DEFINE_PROPERTY_SET (TestObject, test_object, const TestBoxed *, boxed)
+
+void
+test_object_get_boxed (TestObject *self,
+ TestBoxed *value)
+{
+ TestBoxed *boxed;
+
+ g_property_get (G_PROPERTY (test_object_properties[PROP_BOXED]), self, &boxed);
+
+ /* make sure that g_property_get() didn't copy/ref the pointer */
+ g_assert (boxed == self->priv->boxed);
+ g_assert_cmpint (boxed->ref_count, ==, self->priv->boxed->ref_count);
+
+ *value = *boxed;
+}
void
test_object_set_str (TestObject *self,
@@ -210,8 +240,21 @@ test_object_set_str (TestObject *self,
G_DEFINE_PROPERTY_GET (TestObject, test_object, const gchar *, str);
static void
+test_object_finalize (GObject *gobject)
+{
+ TestObjectPrivate *priv = ((TestObject *) gobject)->priv;
+
+ test_boxed_free (priv->boxed);
+ g_free (priv->str);
+
+ G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
+}
+
+static void
test_object_class_init (TestObjectClass *klass)
{
+ G_OBJECT_CLASS (klass)->finalize = test_object_finalize;
+
g_type_class_add_private (klass, sizeof (TestObjectPrivate));
test_object_properties[PROP_FOO] =
@@ -479,7 +522,8 @@ static void
autoproperties_object_set (void)
{
TestObject *t = g_object_new (test_object_get_type (), NULL);
- TestBoxed boxed = { 0, 0, 200, 200, 0 };
+ TestBoxed boxed = { 0, 0, 200, 200, -1 };
+ TestBoxed check;
g_object_set (t,
"foo", 42,
@@ -491,10 +535,9 @@ autoproperties_object_set (void)
g_assert_cmpint (test_object_get_foo (t), ==, 42);
g_assert (test_object_get_bar (t));
g_assert ((test_object_get_flags_value (t) & TEST_FLAGS_VALUE_BAZ) != 0);
- g_assert (test_object_get_boxed (t) != NULL);
- boxed = *test_object_get_boxed (t);
- g_assert_cmpint (boxed.y, ==, 0);
- g_assert_cmpint (boxed.width, ==, 200);
+ test_object_get_boxed (t, &check);
+ g_assert_cmpint (boxed.y, ==, check.y);
+ g_assert_cmpint (boxed.width, ==, check.width);
g_object_unref (t);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]