[glib/g-property] gproperty: Allow control over the copy semantics



commit 9a874591451c3ca9c03d0c6c47dbd64e7820c84b
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Thu Aug 18 11:27:24 2011 +0100

    gproperty: Allow control over the copy semantics
    
    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.

 docs/reference/gobject/gobject-sections.txt |    2 +
 gobject/gobject.symbols                     |    2 +
 gobject/gproperty.c                         |  132 +++++++++++++++++++++------
 gobject/gproperty.h                         |   14 +++-
 gobject/tests/autoproperties.c              |    2 +-
 5 files changed, 122 insertions(+), 30 deletions(-)
---
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt
index 2e3a936..e715525 100644
--- a/docs/reference/gobject/gobject-sections.txt
+++ b/docs/reference/gobject/gobject-sections.txt
@@ -892,6 +892,8 @@ g_property_is_writable
 g_property_is_redable
 g_property_is_deprecated
 g_property_is_atomic
+g_property_is_copy_set
+g_property_is_copy_get
 g_property_describe
 g_property_set_range_values
 g_property_get_range_values
diff --git a/gobject/gobject.symbols b/gobject/gobject.symbols
index 1722924..fde734a 100644
--- a/gobject/gobject.symbols
+++ b/gobject/gobject.symbols
@@ -233,6 +233,8 @@ g_property_get_valist
 g_property_get_value
 g_property_get_value_type
 g_property_is_atomic
+g_property_is_copy_get
+g_property_is_copy_set
 g_property_is_deprecated
 g_property_is_readable
 g_property_is_writable
diff --git a/gobject/gproperty.c b/gobject/gproperty.c
index b94b62b..619cbef 100644
--- a/gobject/gproperty.c
+++ b/gobject/gproperty.c
@@ -2405,8 +2405,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 +2451,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 +2620,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 +2672,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 +2853,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 +2909,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 +4590,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 +4606,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 +4623,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 +5389,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
diff --git a/gobject/gproperty.h b/gobject/gproperty.h
index c156563..72c2c14 100644
--- a/gobject/gproperty.h
+++ b/gobject/gproperty.h
@@ -57,6 +57,13 @@ typedef struct _GProperty       GProperty;
  * @G_PROPERTY_ATOMIC: Whether the autogenerated setter function should
  *   be thread-safe, and acquire a lock when changing the value of the
  *   property.
+ * @G_PROPERTY_COPY_SET: Whether the property will make a copy or
+ *   take a reference when being set to a new value
+ * @G_PROPERTY_COPY_GET: Whether the property will make a copy or
+ *   take a reference when the value is being retrieved
+ * @G_PROPERTY_COPY: Whether the property will make a copy, or take a
+ *   reference, of the new value being set, and return a copy, or
+ *   increase the reference count, of the value being retrieved
  *
  * Flags for properties declared using #GProperty and relative macros.
  *
@@ -70,7 +77,10 @@ typedef enum {
   G_PROPERTY_READWRITE      = (G_PROPERTY_READABLE | G_PROPERTY_WRITABLE),
 
   G_PROPERTY_DEPRECATED     = 1 << 2,
-  G_PROPERTY_ATOMIC         = 1 << 3
+  G_PROPERTY_ATOMIC         = 1 << 3,
+  G_PROPERTY_COPY_SET       = 1 << 4,
+  G_PROPERTY_COPY_GET       = 1 << 5,
+  G_PROPERTY_COPY           = (G_PROPERTY_COPY_SET | G_PROPERTY_COPY_GET)
 } GPropertyFlags;
 
 GType           g_property_get_type             (void) G_GNUC_CONST;
@@ -84,6 +94,8 @@ gboolean        g_property_is_writable                  (GProperty    *property)
 gboolean        g_property_is_readable                  (GProperty    *property);
 gboolean        g_property_is_deprecated                (GProperty    *property);
 gboolean        g_property_is_atomic                    (GProperty    *property);
+gboolean        g_property_is_copy_set                  (GProperty    *property);
+gboolean        g_property_is_copy_get                  (GProperty    *property);
 
 void            g_property_describe                     (GProperty    *property,
                                                          const char   *nick,
diff --git a/gobject/tests/autoproperties.c b/gobject/tests/autoproperties.c
index 69522e8..8fdd948 100644
--- a/gobject/tests/autoproperties.c
+++ b/gobject/tests/autoproperties.c
@@ -333,7 +333,7 @@ test_object_class_init (TestObjectClass *klass)
                           TEST_FLAGS_VALUE_FOO);
 
   test_object_properties[PROP_BOXED] =
-    g_boxed_property_new ("boxed", G_PROPERTY_READWRITE,
+    g_boxed_property_new ("boxed", G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET,
                           G_STRUCT_OFFSET (TestObjectPrivate, boxed),
                           NULL, NULL);
   g_property_set_prerequisite (G_PROPERTY (test_object_properties[PROP_BOXED]),



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]