mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
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
This commit is contained in:
parent
61cb8b232b
commit
88a39670e7
@ -137,7 +137,7 @@ struct _GSettingsBackendClosure
|
|||||||
gchar **names);
|
gchar **names);
|
||||||
|
|
||||||
GMainContext *context;
|
GMainContext *context;
|
||||||
GObject *target;
|
GWeakRef *target_ref;
|
||||||
GSettingsBackend *backend;
|
GSettingsBackend *backend;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
gpointer origin_tag;
|
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
|
* GSettings object in a thread other than the one that is doing the
|
||||||
* dispatching is as follows:
|
* dispatching is as follows:
|
||||||
*
|
*
|
||||||
* 1) hold a GObject reference on the GSettings during an outstanding
|
* 1) hold a thread-safe GWeakRef on the GSettings during an outstanding
|
||||||
* dispatch. This ensures that the delivery is always possible.
|
* 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
|
* 2) hold a weak reference on the GSettings at other times. This
|
||||||
* allows us to receive early notification of pending destruction
|
* 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
|
* possible to keep the object alive using g_object_ref() and we would
|
||||||
* have no way of knowing this.
|
* have no way of knowing this.
|
||||||
*
|
*
|
||||||
* Note also that we do not need to hold a reference on the main
|
* Note also that we need to hold a reference on the main context here
|
||||||
* context here since the GSettings instance does that for us and we
|
* since the GSettings instance may be finalized before the closure runs.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* All access to the list holds a mutex. We have some strategies to
|
* All access to the list holds a mutex. We have some strategies to
|
||||||
* avoid some of the pain that would be associated with that.
|
* 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)
|
g_settings_backend_invoke_closure (gpointer user_data)
|
||||||
{
|
{
|
||||||
GSettingsBackendClosure *closure = user_data;
|
GSettingsBackendClosure *closure = user_data;
|
||||||
|
GObject *target = g_weak_ref_get (closure->target_ref);
|
||||||
|
|
||||||
closure->function (closure->target, closure->backend, closure->name,
|
if (target)
|
||||||
closure->origin_tag, closure->names);
|
{
|
||||||
|
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->backend);
|
||||||
g_object_unref (closure->target);
|
g_weak_ref_clear (closure->target_ref);
|
||||||
|
g_free (closure->target_ref);
|
||||||
g_strfreev (closure->names);
|
g_strfreev (closure->names);
|
||||||
g_free (closure->name);
|
g_free (closure->name);
|
||||||
|
|
||||||
@ -302,8 +307,11 @@ g_settings_backend_dispatch_signal (GSettingsBackend *backend,
|
|||||||
|
|
||||||
closure = g_slice_new (GSettingsBackendClosure);
|
closure = g_slice_new (GSettingsBackendClosure);
|
||||||
closure->context = watch->context;
|
closure->context = watch->context;
|
||||||
|
if (closure->context)
|
||||||
|
g_main_context_ref (closure->context);
|
||||||
closure->backend = g_object_ref (backend);
|
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,
|
closure->function = G_STRUCT_MEMBER (void *, watch->vtable,
|
||||||
function_offset);
|
function_offset);
|
||||||
closure->name = g_strdup (name);
|
closure->name = g_strdup (name);
|
||||||
|
Loading…
Reference in New Issue
Block a user