From cc3221d143889375683a63ed888d984fe8aabe9a Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Mon, 2 Jul 2012 23:34:43 -0400 Subject: Implement change signals Support receiving and properly exposing change notifications. This required some changes to improve the thread-safety of destroying a DConfEngine. It is possible that a signal would be arriving (in the worker thread) at the exact instant that a DConfEngine was being destroyed (from the finalize of the DConfClient or DConfSettingsBackend). This could lead to the object being accessed after it was finalized. We can avoid this by using weak references and by being more careful about when the DConfEngine is freed (by taking a ref to it in the signal handler and releasing it when done). --- gsettings/dconfsettingsbackend.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'gsettings/dconfsettingsbackend.c') diff --git a/gsettings/dconfsettingsbackend.c b/gsettings/dconfsettingsbackend.c index 85aef4e..53a982c 100644 --- a/gsettings/dconfsettingsbackend.c +++ b/gsettings/dconfsettingsbackend.c @@ -140,10 +140,23 @@ dconf_settings_backend_sync (GSettingsBackend *backend) /* XXX implement sync */ } +static void +dconf_settings_backend_free_weak_ref (gpointer data) +{ + GWeakRef *weak_ref = data; + + g_weak_ref_clear (weak_ref); + g_slice_free (GWeakRef, weak_ref); +} + static void dconf_settings_backend_init (DConfSettingsBackend *dcsb) { - dcsb->engine = dconf_engine_new (dcsb); + GWeakRef *weak_ref; + + weak_ref = g_slice_new (GWeakRef); + g_weak_ref_init (weak_ref, dcsb); + dcsb->engine = dconf_engine_new (weak_ref, dconf_settings_backend_free_weak_ref); } static void @@ -151,7 +164,7 @@ dconf_settings_backend_finalize (GObject *object) { DConfSettingsBackend *dcsb = (DConfSettingsBackend *) object; - dconf_engine_free (dcsb->engine); + dconf_engine_unref (dcsb->engine); G_OBJECT_CLASS (dconf_settings_backend_parent_class) ->finalize (object); @@ -202,4 +215,24 @@ dconf_engine_change_notify (DConfEngine *engine, const gchar *tag, gpointer user_data) { + GWeakRef *weak_ref = user_data; + DConfSettingsBackend *dcsb; + + dcsb = g_weak_ref_get (weak_ref); + + if (dcsb == NULL) + return; + + if (changes[0] == NULL) + return; + + if (changes[1] == NULL) + { + if (g_str_has_suffix (prefix, "/")) + g_settings_backend_path_changed (G_SETTINGS_BACKEND (dcsb), prefix, NULL); + else + g_settings_backend_changed (G_SETTINGS_BACKEND (dcsb), prefix, NULL); + } + else + g_settings_backend_keys_changed (G_SETTINGS_BACKEND (dcsb), prefix, changes, NULL); } -- cgit v1.2.1