[glib/g-property: 14/14] gproperty: Allow explicit setters to skip notification



commit 4cf74c3f530c2d04bd3cea6a8e24aaaa8d2663c5
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Thu Jun 9 12:12:11 2011 +0100

    gproperty: Allow explicit setters to skip notification
    
    Explicit setter functions passed when creating a new GProperty should be
    able to skip automatic notification; we simply ask them to return a
    boolean value: TRUE if the value was changed, and FALSE otherwise. This
    allows writing an explicit setter function that only has to deal with
    setting the value and handle its side effects, instead of a more complex
    one that has to acquire and release the property lock and emit the
    notification by itself.

 gobject/gproperty.c            |  102 ++++++++++++++++++++++++++--------------
 gobject/gproperty.h            |   42 ++++++++--------
 gobject/tests/autoproperties.c |    9 ++--
 3 files changed, 92 insertions(+), 61 deletions(-)
---
diff --git a/gobject/gproperty.c b/gobject/gproperty.c
index b358990..cea937e 100644
--- a/gobject/gproperty.c
+++ b/gobject/gproperty.c
@@ -317,6 +317,45 @@
  *       g_object_property_new ("complex", G_PROPERTY_READWRITE, -1,
  *                              test_object_set_complex,
  *                              test_object_get_complex);
+ *     g_property_set_prerequisite (G_PROPERTY (test_object_property[PROP_COMPLEX]),
+ *                                  TEST_TYPE_COMPLEX);
+ * ]|
+ *
+ *     <para>The accessors can be public or private functions. The implementation
+ *     of an explicit setter will be called under the #GProperty lock if the
+ *     property is declared using the %G_PROPERTY_ATOMIC flag; the setter should
+ *     not notify the property on changes, and should return %TRUE if the value
+ *     was modified. An example of a setter is:</para>
+ *
+ * |[
+ *   static gboolean
+ *   test_object_set_complex (gpointer self_,
+ *                            gpointer value_)
+ *   {
+ *     TestObject *self = self_;
+ *     TestComplex *value = value_;
+ *
+ *     if (self->priv->complex == value)
+ *       return FALSE;
+ *
+ *     if (self->priv->complex != NULL)
+ *       {
+ *         test_complex_set_back_pointer (self->priv->complex, NULL);
+ *         g_object_unref (self->priv->complex);
+ *       }
+ *
+ *     self->priv->complex = value;
+ *
+ *     if (self->priv->complex != NULL)
+ *       {
+ *         g_object_ref (self->priv->complex);
+ *         test_complex_set_back_pointer (self->priv->complex, self);
+ *       }
+ *
+ *     test_object_queue_foo (self);
+ *
+ *     return TRUE;
+ *   }
  * ]|
  *
  *     <para>It is also possible to still pass the offset of the structure
@@ -666,13 +705,12 @@ g_##g_t##_property_set_value (GProperty *property, \
     { \
       property_lock_internal (property, gobject); \
 \
-      ((G##G_t##Property *) property)->setter (gobject, value); \
+      retval = ((G##G_t##Property *) property)->setter (gobject, value); \
 \
       property_unlock_internal (property, gobject); \
 \
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property); \
-\
-      retval = TRUE; \
+      if (retval) \
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property); \
     } \
   else if (property->field_offset >= 0) \
     { \
@@ -1333,13 +1371,12 @@ g_enum_property_set_value (GProperty *property,
     {
       property_lock_internal (property, gobject);
 
-      ((GEnumProperty *) property)->setter (gobject, value);
+      retval = ((GEnumProperty *) property)->setter (gobject, value);
 
       property_unlock_internal (property, gobject);
 
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property);
-
-      retval = TRUE;
+      if (retval)
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property);
     }
   else if (property->field_offset >= 0)
     {
@@ -1592,13 +1629,12 @@ g_flags_property_set_value (GProperty *property,
     {
       property_lock_internal (property, gobject);
 
-      ((GFlagsProperty *) property)->setter (gobject, value);
+      retval = ((GFlagsProperty *) property)->setter (gobject, value);
 
       property_unlock_internal (property, gobject);
 
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property);
-
-      retval = TRUE;
+      if (retval)
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property);
     }
   else if (property->field_offset >= 0)
     {
@@ -1871,13 +1907,12 @@ g_float_property_set_value (GProperty *property,
     {
       property_lock_internal (property, gobject);
 
-      ((GFloatProperty *) property)->setter (gobject, value);
+      retval = ((GFloatProperty *) property)->setter (gobject, value);
 
       property_unlock_internal (property, gobject);
 
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property);
-
-      retval = TRUE;
+      if (retval)
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property);
     }
   else if (property->field_offset >= 0)
     {
@@ -2150,13 +2185,12 @@ g_double_property_set_value (GProperty *property,
     {
       property_lock_internal (property, gobject);
 
-      ((GDoubleProperty *) property)->setter (gobject, value);
+      retval = ((GDoubleProperty *) property)->setter (gobject, value);
 
       property_unlock_internal (property, gobject);
 
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property);
-
-      retval = TRUE;
+      if (retval)
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property);
     }
   else if (property->field_offset >= 0)
     {
@@ -2356,13 +2390,12 @@ g_string_property_set_value (GProperty   *property,
     {
       property_lock_internal (property, gobject);
 
-      ((GStringProperty *) property)->setter (gobject, value);
+      retval = ((GStringProperty *) property)->setter (gobject, value);
 
       property_unlock_internal (property, gobject);
 
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property);
-
-      retval = TRUE;
+      if (retval)
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property);
     }
   else if (property->field_offset >= 0)
     {
@@ -2572,13 +2605,12 @@ g_boxed_property_set_value (GProperty *property,
     {
       property_lock_internal (property, gobject);
 
-      ((GBoxedProperty *) property)->setter (gobject, value);
+      retval = ((GBoxedProperty *) property)->setter (gobject, value);
 
       property_unlock_internal (property, gobject);
 
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property);
-
-      retval = TRUE;
+      if (retval)
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property);
     }
   else if (property->field_offset >= 0)
     {
@@ -2789,13 +2821,12 @@ g_object_property_set_value (GProperty *property,
     {
       property_lock_internal (property, gobject);
 
-      ((GObjectProperty *) property)->setter (gobject, value);
+      retval = ((GObjectProperty *) property)->setter (gobject, value);
 
       property_unlock_internal (property, gobject);
 
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property);
-
-      retval = TRUE;
+      if (retval)
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property);
     }
   else if (property->field_offset >= 0)
     {
@@ -3010,13 +3041,12 @@ g_pointer_property_set_value (GProperty *property,
     {
       property_lock_internal (property, gobject);
 
-      ((GPointerProperty *) property)->setter (gobject, value);
+      retval = ((GPointerProperty *) property)->setter (gobject, value);
 
       property_unlock_internal (property, gobject);
 
-      g_object_notify_by_pspec (gobject, (GParamSpec *) property);
-
-      retval = TRUE;
+      if (retval)
+        g_object_notify_by_pspec (gobject, (GParamSpec *) property);
     }
   else if (property->field_offset >= 0)
     {
diff --git a/gobject/gproperty.h b/gobject/gproperty.h
index 668f773..3b73106 100644
--- a/gobject/gproperty.h
+++ b/gobject/gproperty.h
@@ -180,87 +180,87 @@ void            _g_property_set_installed       (GProperty           *property,
                                                  GType                class_gtype);
 
 /* per-type specific accessors */
-typedef void          (* GPropertyBooleanSet) (gpointer       gobject,
+typedef gboolean      (* GPropertyBooleanSet) (gpointer       gobject,
                                                gboolean       value);
 typedef gboolean      (* GPropertyBooleanGet) (gpointer       gobject);
 
-typedef void          (* GPropertyIntSet)     (gpointer       gobject,
+typedef gboolean      (* GPropertyIntSet)     (gpointer       gobject,
                                                gint           value);
 typedef gint          (* GPropertyIntGet)     (gpointer       gobject);
 
-typedef void          (* GPropertyInt8Set)    (gpointer       gobject,
+typedef gboolean      (* GPropertyInt8Set)    (gpointer       gobject,
                                                gint8          value);
 typedef gint8         (* GPropertyInt8Get)    (gpointer       gobject);
 
-typedef void          (* GPropertyInt16Set)   (gpointer       gobject,
+typedef gboolean      (* GPropertyInt16Set)   (gpointer       gobject,
                                                gint16         value);
 typedef gint16        (* GPropertyInt16Get)   (gpointer       gobject);
 
-typedef void          (* GPropertyInt32Set)   (gpointer       gobject,
+typedef gboolean      (* GPropertyInt32Set)   (gpointer       gobject,
                                                gint32         value);
 typedef gint32        (* GPropertyInt32Get)   (gpointer       gobject);
 
-typedef void          (* GPropertyInt64Set)   (gpointer       gobject,
+typedef gboolean      (* GPropertyInt64Set)   (gpointer       gobject,
                                                gint64         value);
 typedef gint64        (* GPropertyInt64Get)   (gpointer       gobject);
 
-typedef void          (* GPropertyLongSet)    (gpointer       gobject,
+typedef gboolean      (* GPropertyLongSet)    (gpointer       gobject,
                                                glong          value);
 typedef glong         (* GPropertyLongGet)    (gpointer       gobject);
 
-typedef void          (* GPropertyUIntSet)    (gpointer       gobject,
+typedef gboolean      (* GPropertyUIntSet)    (gpointer       gobject,
                                                guint          value);
 typedef guint         (* GPropertyUIntGet)    (gpointer       gobject);
 
-typedef void          (* GPropertyUInt8Set)   (gpointer       gobject,
+typedef gboolean      (* GPropertyUInt8Set)   (gpointer       gobject,
                                                guint8         value);
 typedef guint8        (* GPropertyUInt8Get)   (gpointer       gobject);
 
-typedef void          (* GPropertyUInt16Set)  (gpointer       gobject,
+typedef gboolean      (* GPropertyUInt16Set)  (gpointer       gobject,
                                                guint16        value);
 typedef guint16       (* GPropertyUInt16Get)  (gpointer       gobject);
 
-typedef void          (* GPropertyUInt32Set)  (gpointer       gobject,
+typedef gboolean      (* GPropertyUInt32Set)  (gpointer       gobject,
                                                guint32        value);
 typedef guint32       (* GPropertyUInt32Get)  (gpointer       gobject);
 
-typedef void          (* GPropertyUInt64Set)  (gpointer       gobject,
+typedef gboolean      (* GPropertyUInt64Set)  (gpointer       gobject,
                                                guint64        value);
 typedef guint64       (* GPropertyUInt64Get)  (gpointer       gobject);
 
-typedef void          (* GPropertyULongSet)   (gpointer       gobject,
+typedef gboolean      (* GPropertyULongSet)   (gpointer       gobject,
                                                gulong         value);
 typedef gulong        (* GPropertyULongGet)   (gpointer       gobject);
 
-typedef void          (* GPropertyEnumSet)    (gpointer       gobject,
+typedef gboolean      (* GPropertyEnumSet)    (gpointer       gobject,
                                                glong          value);
 typedef glong         (* GPropertyEnumGet)    (gpointer       gobject);
 
-typedef void          (* GPropertyFlagsSet)   (gpointer       gobject,
+typedef gboolean      (* GPropertyFlagsSet)   (gpointer       gobject,
                                                glong          value);
 typedef glong         (* GPropertyFlagsGet)   (gpointer       gobject);
 
-typedef void          (* GPropertyFloatSet)   (gpointer       gobject,
+typedef gboolean      (* GPropertyFloatSet)   (gpointer       gobject,
                                                gfloat         value);
 typedef gfloat        (* GPropertyFloatGet)   (gpointer       gobject);
 
-typedef void          (* GPropertyDoubleSet)  (gpointer       gobject,
+typedef gboolean      (* GPropertyDoubleSet)  (gpointer       gobject,
                                                gdouble        value);
 typedef gdouble       (* GPropertyDoubleGet)  (gpointer       gobject);
 
-typedef void          (* GPropertyStringSet)  (gpointer       gobject,
+typedef gboolean      (* GPropertyStringSet)  (gpointer       gobject,
                                                const char    *value);
 typedef const char *  (* GPropertyStringGet)  (gpointer       gobject);
 
-typedef void          (* GPropertyBoxedSet)   (gpointer       gobject,
+typedef gboolean      (* GPropertyBoxedSet)   (gpointer       gobject,
                                                gpointer       value);
 typedef gpointer      (* GPropertyBoxedGet)   (gpointer       gobject);
 
-typedef void          (* GPropertyObjectSet)  (gpointer       gobject,
+typedef gboolean      (* GPropertyObjectSet)  (gpointer       gobject,
                                                gpointer       value);
 typedef gpointer      (* GPropertyObjectGet)  (gpointer       gobject);
 
-typedef void          (* GPropertyPointerSet) (gpointer       gobject,
+typedef gboolean      (* GPropertyPointerSet) (gpointer       gobject,
                                                gpointer       value);
 typedef gpointer      (* GPropertyPointerGet) (gpointer       gobject);
 
diff --git a/gobject/tests/autoproperties.c b/gobject/tests/autoproperties.c
index 2f2127b..69522e8 100644
--- a/gobject/tests/autoproperties.c
+++ b/gobject/tests/autoproperties.c
@@ -212,18 +212,18 @@ test_object_get_boxed (TestObject *self,
   *value = *boxed;
 }
 
-void
+gboolean
 test_object_set_str (TestObject  *self,
                      const gchar *value)
 {
   TestObjectPrivate *priv;
 
-  g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (self, test_object_get_type ()));
+  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (self, test_object_get_type ()), FALSE);
 
   priv = self->priv;
 
   if (g_strcmp0 (priv->str, value) == 0)
-    return;
+    return FALSE;
 
   g_free (priv->str);
   priv->str = g_strdup (value);
@@ -233,8 +233,9 @@ test_object_set_str (TestObject  *self,
   else
     priv->str_set = FALSE;
 
-  g_object_notify_by_pspec (G_OBJECT (self), test_object_properties[PROP_STR]);
   g_object_notify_by_pspec (G_OBJECT (self), test_object_properties[PROP_STR_SET]);
+
+  return TRUE;
 }
 
 G_DEFINE_PROPERTY_GET (TestObject, test_object, const gchar *, str);



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