[glib/wip/settings-backend: 3/14] GSettingsBackend: move 'has-unapplied' logic here



commit ddc12323d1e65a97b8dfdf27f9798e69f85491a1
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Dec 29 04:58:20 2011 -0500

    GSettingsBackend: move 'has-unapplied' logic here
    
    Add GSettingsBackend API to allow any backend to have a 'has-unapplied'
    property.  Remove the 'owner' hackery that was used for notifying of
    changes to 'has-unapplied' and just use normal GObject notify (and wire
    into that from the frontend).

 gio/gdelayedsettingsbackend.c  |   93 +++------------------------------------
 gio/gdelayedsettingsbackend.h  |    6 +--
 gio/gio.symbols                |    1 +
 gio/gsettings.c                |   31 ++++++++++---
 gio/gsettingsbackend.c         |   42 ++++++++++++++++++
 gio/gsettingsbackend.h         |    2 +
 gio/gsettingsbackendinternal.h |    2 +
 7 files changed, 80 insertions(+), 97 deletions(-)
---
diff --git a/gio/gdelayedsettingsbackend.c b/gio/gdelayedsettingsbackend.c
index a891fe1..e45da36 100644
--- a/gio/gdelayedsettingsbackend.c
+++ b/gio/gdelayedsettingsbackend.c
@@ -32,48 +32,12 @@ struct _GDelayedSettingsBackendPrivate
   GSettingsBackend *backend;
   GMutex lock;
   GTree *delayed;
-
-  GMainContext *owner_context;
-  gpointer owner;
 };
 
 G_DEFINE_TYPE (GDelayedSettingsBackend,
                g_delayed_settings_backend,
                G_TYPE_SETTINGS_BACKEND)
 
-static gboolean
-invoke_notify_unapplied (gpointer data)
-{
-  g_object_notify (data, "has-unapplied");
-  g_object_unref (data);
-
-  return FALSE;
-}
-
-static void
-g_delayed_settings_backend_notify_unapplied (GDelayedSettingsBackend *delayed)
-{
-  GMainContext *target_context;
-  GObject *target;
-
-  g_mutex_lock (&delayed->priv->lock);
-  if (delayed->priv->owner)
-    {
-      target_context = delayed->priv->owner_context;
-      target = g_object_ref (delayed->priv->owner);
-    }
-  else
-    {
-      target_context = NULL;
-      target = NULL;
-    }
-  g_mutex_unlock (&delayed->priv->lock);
-
-  if (target != NULL)
-    g_main_context_invoke (target_context, invoke_notify_unapplied, target);
-}
-
-
 static GVariant *
 g_delayed_settings_backend_read (GSettingsBackend   *backend,
                                  const gchar        *key,
@@ -111,18 +75,13 @@ g_delayed_settings_backend_write (GSettingsBackend *backend,
                                   gpointer          origin_tag)
 {
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
-  gboolean was_empty;
 
   g_mutex_lock (&delayed->priv->lock);
-  was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
-  g_tree_insert (delayed->priv->delayed, g_strdup (key),
-                 g_variant_ref_sink (value));
+  g_tree_insert (delayed->priv->delayed, g_strdup (key), g_variant_ref_sink (value));
   g_mutex_unlock (&delayed->priv->lock);
 
   g_settings_backend_changed (backend, key, origin_tag);
-
-  if (was_empty)
-    g_delayed_settings_backend_notify_unapplied (delayed);
+  g_settings_backend_set_has_unapplied (backend, TRUE);
 
   return TRUE;
 }
@@ -142,18 +101,13 @@ g_delayed_settings_backend_write_tree (GSettingsBackend *backend,
                                        gpointer          origin_tag)
 {
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
-  gboolean was_empty;
 
   g_mutex_lock (&delayed->priv->lock);
-  was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
-
   g_tree_foreach (tree, add_to_tree, delayed->priv->delayed);
   g_mutex_unlock (&delayed->priv->lock);
 
   g_settings_backend_changed_tree (backend, tree, origin_tag);
-
-  if (was_empty)
-    g_delayed_settings_backend_notify_unapplied (delayed);
+  g_settings_backend_set_has_unapplied (backend, TRUE);
 
   return TRUE;
 }
@@ -173,15 +127,13 @@ g_delayed_settings_backend_reset (GSettingsBackend *backend,
                                   gpointer          origin_tag)
 {
   GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
-  gboolean was_empty;
 
   g_mutex_lock (&delayed->priv->lock);
-  was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
   g_tree_insert (delayed->priv->delayed, g_strdup (key), NULL);
   g_mutex_unlock (&delayed->priv->lock);
 
-  if (was_empty)
-    g_delayed_settings_backend_notify_unapplied (delayed);
+  g_settings_backend_changed (backend, key, origin_tag);
+  g_settings_backend_set_has_unapplied (backend, TRUE);
 }
 
 static void
@@ -213,14 +165,6 @@ g_delayed_settings_backend_get_permission (GSettingsBackend *backend,
 
 
 /* method calls */
-gboolean
-g_delayed_settings_backend_get_has_unapplied (GDelayedSettingsBackend *delayed)
-{
-  /* we don't need to lock for this... */
-
-  return g_tree_nnodes (delayed->priv->delayed) > 0;
-}
-
 void
 g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed)
 {
@@ -242,7 +186,7 @@ g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed)
 
       g_tree_unref (tmp);
 
-      g_delayed_settings_backend_notify_unapplied (delayed);
+      g_settings_backend_set_has_unapplied (G_SETTINGS_BACKEND (delayed), FALSE);
     }
 }
 
@@ -260,7 +204,7 @@ g_delayed_settings_backend_revert (GDelayedSettingsBackend *delayed)
       g_settings_backend_changed_tree (G_SETTINGS_BACKEND (delayed), tmp, NULL);
       g_tree_unref (tmp);
 
-      g_delayed_settings_backend_notify_unapplied (delayed);
+      g_settings_backend_set_has_unapplied (G_SETTINGS_BACKEND (delayed), FALSE);
     }
 }
 
@@ -283,9 +227,6 @@ g_delayed_settings_backend_finalize (GObject *object)
   g_object_unref (delayed->priv->backend);
   g_tree_unref (delayed->priv->delayed);
 
-  /* if our owner is still alive, why are we finalizing? */
-  g_assert (delayed->priv->owner == NULL);
-
   G_OBJECT_CLASS (g_delayed_settings_backend_parent_class)
     ->finalize (object);
 }
@@ -321,31 +262,13 @@ g_delayed_settings_backend_init (GDelayedSettingsBackend *delayed)
   g_mutex_init (&delayed->priv->lock);
 }
 
-static void
-g_delayed_settings_backend_disown (gpointer  data,
-                                   GObject  *where_the_object_was)
-{
-  GDelayedSettingsBackend *delayed = data;
-
-  g_mutex_lock (&delayed->priv->lock);
-  delayed->priv->owner_context = NULL;
-  delayed->priv->owner = NULL;
-  g_mutex_unlock (&delayed->priv->lock);
-}
-
 GDelayedSettingsBackend *
-g_delayed_settings_backend_new (GSettingsBackend *backend,
-                                gpointer          owner,
-                                GMainContext     *owner_context)
+g_delayed_settings_backend_new (GSettingsBackend *backend)
 {
   GDelayedSettingsBackend *delayed;
 
   delayed = g_object_new (G_TYPE_DELAYED_SETTINGS_BACKEND, NULL);
   delayed->priv->backend = g_object_ref (backend);
-  delayed->priv->owner_context = owner_context;
-  delayed->priv->owner = owner;
-
-  g_object_weak_ref (owner, g_delayed_settings_backend_disown, delayed);
 
   g_settings_backend_watch (delayed->priv->backend, g_delayed_settings_got_event, G_OBJECT (delayed));
 
diff --git a/gio/gdelayedsettingsbackend.h b/gio/gdelayedsettingsbackend.h
index 34ec3ef..b11cae6 100644
--- a/gio/gdelayedsettingsbackend.h
+++ b/gio/gdelayedsettingsbackend.h
@@ -59,14 +59,10 @@ struct _GDelayedSettingsBackend
 G_GNUC_INTERNAL
 GType                           g_delayed_settings_backend_get_type     (void);
 G_GNUC_INTERNAL
-GDelayedSettingsBackend *       g_delayed_settings_backend_new          (GSettingsBackend        *backend,
-                                                                         gpointer                 owner,
-                                                                         GMainContext            *owner_context);
+GDelayedSettingsBackend *       g_delayed_settings_backend_new          (GSettingsBackend        *backend);
 G_GNUC_INTERNAL
 void                            g_delayed_settings_backend_revert       (GDelayedSettingsBackend *delayed);
 G_GNUC_INTERNAL
 void                            g_delayed_settings_backend_apply        (GDelayedSettingsBackend *delayed);
-G_GNUC_INTERNAL
-gboolean                        g_delayed_settings_backend_get_has_unapplied (GDelayedSettingsBackend *delayed);
 
 #endif  /* __G_DELAYED_SETTINGS_BACKEND_H__ */
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 3c7cc0c..9907f04 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1133,6 +1133,7 @@ g_file_descriptor_based_get_fd
 #endif
 g_settings_backend_get_type
 g_settings_backend_report_event
+g_settings_backend_set_has_unapplied
 g_settings_backend_changed
 g_settings_backend_flatten_tree
 g_settings_backend_keys_changed
diff --git a/gio/gsettings.c b/gio/gsettings.c
index 4c828b3..9f1f1f3 100644
--- a/gio/gsettings.c
+++ b/gio/gsettings.c
@@ -514,6 +514,25 @@ g_settings_got_event (GObject              *target,
     }
 }
 
+static gboolean
+g_settings_emit_has_unapplied_notify (gpointer data)
+{
+  g_object_notify (data, "has-unapplied");
+  g_object_unref (data);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+g_settings_got_has_unapplied_notify (GSettingsBackend *backend,
+                                     GParamSpec       *pspec,
+                                     gpointer          user_data)
+{
+  GSettings *settings = G_SETTINGS (user_data);
+
+  g_main_context_invoke (settings->priv->main_context, g_settings_emit_has_unapplied_notify, g_object_ref (settings));
+}
+
 /* Properties, Construction, Destruction {{{1 */
 static void
 g_settings_set_property (GObject      *object,
@@ -658,6 +677,7 @@ g_settings_finalize (GObject *object)
 {
   GSettings *settings = G_SETTINGS (object);
 
+  g_signal_handlers_disconnect_by_func (settings->priv->backend, g_settings_got_has_unapplied_notify, settings);
   g_settings_backend_unsubscribe (settings->priv->backend,
                                   settings->priv->path);
   g_main_context_unref (settings->priv->main_context);
@@ -1966,16 +1986,15 @@ g_settings_delay (GSettings *settings)
   if (settings->priv->delayed)
     return;
 
-  settings->priv->delayed =
-    g_delayed_settings_backend_new (settings->priv->backend,
-                                    settings,
-                                    settings->priv->main_context);
+  settings->priv->delayed = g_delayed_settings_backend_new (settings->priv->backend);
   g_settings_backend_unwatch (settings->priv->backend, G_OBJECT (settings));
   g_object_unref (settings->priv->backend);
 
   settings->priv->backend = G_SETTINGS_BACKEND (settings->priv->delayed);
   g_settings_backend_watch (settings->priv->backend, g_settings_got_event, G_OBJECT (settings));
 
+  g_signal_connect (settings->priv->delayed, "notify::has-unapplied",
+                    G_CALLBACK (g_settings_got_has_unapplied_notify), settings);
   g_object_notify (G_OBJECT (settings), "delay-apply");
 }
 
@@ -2039,9 +2058,7 @@ g_settings_get_has_unapplied (GSettings *settings)
 {
   g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
 
-  return settings->priv->delayed &&
-         g_delayed_settings_backend_get_has_unapplied (
-           G_DELAYED_SETTINGS_BACKEND (settings->priv->backend));
+  return g_settings_backend_get_has_unapplied (settings->priv->backend);
 }
 
 /* Extra API (reset, sync, get_child, is_writable, list_*, ranges) {{{1 */
diff --git a/gio/gsettingsbackend.c b/gio/gsettingsbackend.c
index 7d4eb05..f8d1eb7 100644
--- a/gio/gsettingsbackend.c
+++ b/gio/gsettingsbackend.c
@@ -40,9 +40,19 @@ typedef struct _GSettingsBackendWatch   GSettingsBackendWatch;
 struct _GSettingsBackendPrivate
 {
   GSettingsBackendWatch *watches;
+  gboolean has_unapplied;
   GMutex lock;
 };
 
+enum
+{
+  PROP_0,
+  PROP_HAS_UNAPPLIED,
+  N_PROPS
+};
+
+static GParamSpec *g_settings_backend_pspecs[N_PROPS];
+
 /* For g_settings_backend_sync_default(), we only want to actually do
  * the sync if the backend already exists.  This avoids us creating an
  * entire GSettingsBackend in order to call a do-nothing sync()
@@ -808,6 +818,14 @@ g_settings_backend_subscribe (GSettingsBackend *backend,
 }
 
 static void
+g_settings_backend_get_property (GObject *object, guint prop_id,
+                                 GValue *value, GParamSpec *pspec)
+{
+  g_assert (prop_id == PROP_HAS_UNAPPLIED);
+  g_value_set_boolean (value, g_settings_backend_get_has_unapplied (G_SETTINGS_BACKEND (object)));
+}
+
+static void
 g_settings_backend_finalize (GObject *object)
 {
   GSettingsBackend *backend = G_SETTINGS_BACKEND (object);
@@ -841,8 +859,14 @@ g_settings_backend_class_init (GSettingsBackendClass *class)
   class->subscribe = ignore_subscription;
   class->unsubscribe = ignore_subscription;
 
+  gobject_class->get_property = g_settings_backend_get_property;
   gobject_class->finalize = g_settings_backend_finalize;
 
+  g_settings_backend_pspecs[PROP_HAS_UNAPPLIED] =
+    g_param_spec_boolean ("has-unapplied", "has unapplied", "TRUE if apply() is meaningful",
+                          FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_properties (gobject_class, N_PROPS, g_settings_backend_pspecs);
+
   g_type_class_add_private (class, sizeof (GSettingsBackendPrivate));
 }
 
@@ -954,3 +978,21 @@ g_settings_backend_sync_default (void)
         class->sync (backend);
     }
 }
+
+gboolean
+g_settings_backend_get_has_unapplied (GSettingsBackend *backend)
+{
+  return backend->priv->has_unapplied;
+}
+
+void
+g_settings_backend_set_has_unapplied (GSettingsBackend *backend,
+                                      gboolean          has_unapplied)
+{
+  if (has_unapplied != backend->priv->has_unapplied)
+    {
+      backend->priv->has_unapplied = has_unapplied;
+
+      g_object_notify_by_pspec (G_OBJECT (backend), g_settings_backend_pspecs[PROP_HAS_UNAPPLIED]);
+    }
+}
diff --git a/gio/gsettingsbackend.h b/gio/gsettingsbackend.h
index f75136f..b7f89e7 100644
--- a/gio/gsettingsbackend.h
+++ b/gio/gsettingsbackend.h
@@ -122,6 +122,8 @@ GType                   g_settings_backend_get_type                     (void);
 
 void                    g_settings_backend_report_event                 (GSettingsBackend     *backend,
                                                                          const GSettingsEvent *event);
+void                    g_settings_backend_set_has_unapplied            (GSettingsBackend     *backend,
+                                                                         gboolean              has_unapplied);
 void                    g_settings_backend_changed                      (GSettingsBackend     *backend,
                                                                          const gchar          *key,
                                                                          gpointer              origin_tag);
diff --git a/gio/gsettingsbackendinternal.h b/gio/gsettingsbackendinternal.h
index 3da1232..85494ff 100644
--- a/gio/gsettingsbackendinternal.h
+++ b/gio/gsettingsbackendinternal.h
@@ -71,6 +71,8 @@ G_GNUC_INTERNAL
 GPermission *           g_settings_backend_get_permission               (GSettingsBackend     *backend,
                                                                          const gchar          *path);
 G_GNUC_INTERNAL
+gboolean                g_settings_backend_get_has_unapplied            (GSettingsBackend     *backend);
+G_GNUC_INTERNAL
 void                    g_settings_backend_sync_default                 (void);
 
 G_GNUC_INTERNAL



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