+static void
+g_settings_backend_dispatch_signal (GSettingsBackend *backend,
+ gsize function_offset,
+ const gchar *name,
+ gpointer origin_tag,
+ const gchar * const *names)
+{
+ GSettingsBackendWatch *watch;
+ GSList *closures = NULL;
+
+ /* We're in a little bit of a tricky situation here. We need to hold
+ * a lock while traversing the list, but we don't want to hold the
+ * lock while calling back into user code.
+ *
+ * We work around this by creating a bunch of GSettingsBackendClosure
+ * objects while holding the lock and dispatching them after. We
+ * never touch the list without holding the lock.
+ */
+ g_mutex_lock (&backend->priv->lock);
+ for (watch = backend->priv->watches; watch; watch = watch->next)
+ {
+ GSettingsBackendClosure *closure;
+
+ closure = g_slice_new (GSettingsBackendClosure);
+ closure->context = watch->context;
+ closure->backend = g_object_ref (backend);
+ closure->target = g_object_ref (watch->target);
+ closure->function = G_STRUCT_MEMBER (void *, watch->vtable,
+ function_offset);
+ closure->name = g_strdup (name);
+ closure->origin_tag = origin_tag;
+ closure->names = g_strdupv ((gchar **) names);
+
+ closures = g_slist_prepend (closures, closure);
+ }
+ g_mutex_unlock (&backend->priv->lock);
+
+ while (closures)
+ {
+ GSettingsBackendClosure *closure = closures->data;
+
+ if (closure->context)
+ g_main_context_invoke (closure->context,
+ g_settings_backend_invoke_closure,
+ closure);
+ else
+ g_settings_backend_invoke_closure (closure);
+
+ closures = g_slist_delete_link (closures, closures);
+ }