From ddc12323d1e65a97b8dfdf27f9798e69f85491a1 Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Thu, 29 Dec 2011 04:58:20 -0500 Subject: [PATCH] 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 a891fe1b3..e45da36af 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 34ec3efb7..b11cae641 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 3c7cc0ca2..9907f04e6 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 4c828b3b4..9f1f1f330 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 7d4eb055c..f8d1eb752 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() @@ -807,6 +817,14 @@ g_settings_backend_subscribe (GSettingsBackend *backend, ->subscribe (backend, name); } +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) { @@ -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 f75136fa3..b7f89e7ec 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 3da1232f2..85494fff8 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