[glib] GSettingsBackend: use a GWeakRef during dispatch
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] GSettingsBackend: use a GWeakRef during dispatch
- Date: Fri, 8 Sep 2017 18:24:51 +0000 (UTC)
commit 88a39670e70c3bbe6d1be37fd2c3506c50ede6dd
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Sun Aug 27 12:15:37 2017 -0700
GSettingsBackend: use a GWeakRef during dispatch
Instead of a full reference, which causes problems for clients that
expect a GSettings instance to stop firing signals once they drop the
last reference.
https://bugzilla.gnome.org/show_bug.cgi?id=780861
gio/gsettingsbackend.c | 34 +++++++++++++++++++++-------------
1 files changed, 21 insertions(+), 13 deletions(-)
---
diff --git a/gio/gsettingsbackend.c b/gio/gsettingsbackend.c
index 281ae8e..0d5df0f 100644
--- a/gio/gsettingsbackend.c
+++ b/gio/gsettingsbackend.c
@@ -137,7 +137,7 @@ struct _GSettingsBackendClosure
gchar **names);
GMainContext *context;
- GObject *target;
+ GWeakRef *target_ref;
GSettingsBackend *backend;
gchar *name;
gpointer origin_tag;
@@ -208,8 +208,9 @@ g_settings_backend_watch (GSettingsBackend *backend,
* GSettings object in a thread other than the one that is doing the
* dispatching is as follows:
*
- * 1) hold a GObject reference on the GSettings during an outstanding
- * dispatch. This ensures that the delivery is always possible.
+ * 1) hold a thread-safe GWeakRef on the GSettings during an outstanding
+ * dispatch. This ensures that the delivery is always possible while
+ * the GSettings object is alive.
*
* 2) hold a weak reference on the GSettings at other times. This
* allows us to receive early notification of pending destruction
@@ -224,12 +225,8 @@ g_settings_backend_watch (GSettingsBackend *backend,
* possible to keep the object alive using g_object_ref() and we would
* have no way of knowing this.
*
- * Note also that we do not need to hold a reference on the main
- * context here since the GSettings instance does that for us and we
- * will receive the weak notify long before it is dropped. We don't
- * even need to hold it during dispatches because our reference on the
- * GSettings will prevent the finalize from running and dropping the
- * ref on the context.
+ * Note also that we need to hold a reference on the main context here
+ * since the GSettings instance may be finalized before the closure runs.
*
* All access to the list holds a mutex. We have some strategies to
* avoid some of the pain that would be associated with that.
@@ -263,12 +260,20 @@ static gboolean
g_settings_backend_invoke_closure (gpointer user_data)
{
GSettingsBackendClosure *closure = user_data;
+ GObject *target = g_weak_ref_get (closure->target_ref);
- closure->function (closure->target, closure->backend, closure->name,
- closure->origin_tag, closure->names);
+ if (target)
+ {
+ closure->function (target, closure->backend, closure->name,
+ closure->origin_tag, closure->names);
+ g_object_unref (target);
+ }
+ if (closure->context)
+ g_main_context_unref (closure->context);
g_object_unref (closure->backend);
- g_object_unref (closure->target);
+ g_weak_ref_clear (closure->target_ref);
+ g_free (closure->target_ref);
g_strfreev (closure->names);
g_free (closure->name);
@@ -302,8 +307,11 @@ g_settings_backend_dispatch_signal (GSettingsBackend *backend,
closure = g_slice_new (GSettingsBackendClosure);
closure->context = watch->context;
+ if (closure->context)
+ g_main_context_ref (closure->context);
closure->backend = g_object_ref (backend);
- closure->target = g_object_ref (watch->target);
+ closure->target_ref = g_new (GWeakRef, 1);
+ g_weak_ref_init (closure->target_ref, watch->target);
closure->function = G_STRUCT_MEMBER (void *, watch->vtable,
function_offset);
closure->name = g_strdup (name);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]