* implementations, but does not carry the same stability guarantees
* as the public GIO API. For this reason, you have to define the
* C preprocessor symbol %G_SETTINGS_ENABLE_BACKEND before including
- * <filename>gio/gsettingsbackend.h</filename>
+ * `gio/gsettingsbackend.h`.
**/
static gboolean
struct _GSettingsBackendClosure
{
- void (*function) (GObject *target,
- GSettingsBackend *backend,
- const gchar *name,
- gpointer data1,
- gpointer data2);
-
- GSettingsBackend *backend;
- GObject *target;
- gchar *name;
- gpointer data1;
- GBoxedFreeFunc data1_free;
- gpointer data2;
+ void (*function) (GObject *target,
+ GSettingsBackend *backend,
+ const gchar *name,
+ gpointer origin_tag,
+ gchar **names);
+
+ GMainContext *context;
+ GObject *target;
+ GSettingsBackend *backend;
+ gchar *name;
+ gpointer origin_tag;
+ gchar **names;
};
static void
GSettingsBackendClosure *closure = user_data;
closure->function (closure->target, closure->backend, closure->name,
- closure->data1, closure->data2);
+ closure->origin_tag, closure->names);
- closure->data1_free (closure->data1);
g_object_unref (closure->backend);
g_object_unref (closure->target);
+ g_strfreev (closure->names);
g_free (closure->name);
g_slice_free (GSettingsBackendClosure, closure);
return FALSE;
}
-static gpointer
-pointer_id (gpointer a)
-{
- return a;
-}
-
static void
-pointer_ignore (gpointer a)
+g_settings_backend_dispatch_signal (GSettingsBackend *backend,
+ gsize function_offset,
+ const gchar *name,
+ gpointer origin_tag,
+ const gchar * const *names)
{
-}
-
-static void
-g_settings_backend_dispatch_signal (GSettingsBackend *backend,
- gsize function_offset,
- const gchar *name,
- gpointer data1,
- GBoxedCopyFunc data1_copy,
- GBoxedFreeFunc data1_free,
- gpointer data2)
-{
- GSettingsBackendWatch *suffix, *watch, *next;
-
- if (data1_copy == NULL)
- data1_copy = pointer_id;
-
- if (data1_free == NULL)
- data1_free = pointer_ignore;
+ 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.
*
- * Since we're not holding the lock while we call user code, we can't
- * render the list immutable. We can, however, store a pointer to a
- * given suffix of the list and render that suffix immutable.
- *
- * Adds will never modify the suffix since adds always come in the
- * form of prepends. We can also prevent removes from modifying the
- * suffix since removes only happen in response to the last reference
- * count dropping -- so just add a reference to everything in the
- * suffix.
+ * 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);
- suffix = backend->priv->watches;
- for (watch = suffix; watch; watch = watch->next)
- g_object_ref (watch->target);
- g_mutex_unlock (&backend->priv->lock);
-
- /* The suffix is now immutable, so this is safe. */
- for (watch = suffix; watch; watch = next)
+ 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 = watch->target; /* we took our ref above */
+ closure->target = g_object_ref (watch->target);
closure->function = G_STRUCT_MEMBER (void *, watch->vtable,
function_offset);
closure->name = g_strdup (name);
- closure->data1 = data1_copy (data1);
- closure->data1_free = data1_free;
- closure->data2 = data2;
+ closure->origin_tag = origin_tag;
+ closure->names = g_strdupv ((gchar **) names);
- /* we do this here because 'watch' may not live to the end of this
- * iteration of the loop (since we may unref the target below).
- */
- next = watch->next;
+ closures = g_slist_prepend (closures, closure);
+ }
+ g_mutex_unlock (&backend->priv->lock);
- if (watch->context)
- g_main_context_invoke (watch->context,
+ 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);
}
}
g_settings_backend_dispatch_signal (backend,
G_STRUCT_OFFSET (GSettingsListenerVTable,
changed),
- key, origin_tag, NULL, NULL, NULL);
+ key, origin_tag, NULL);
}
/**
g_settings_backend_dispatch_signal (backend,
G_STRUCT_OFFSET (GSettingsListenerVTable,
keys_changed),
- path, (gpointer) items,
- (GBoxedCopyFunc) g_strdupv,
- (GBoxedFreeFunc) g_strfreev,
- origin_tag);
+ path, origin_tag, items);
}
/**
g_settings_backend_dispatch_signal (backend,
G_STRUCT_OFFSET (GSettingsListenerVTable,
path_changed),
- path, origin_tag, NULL, NULL, NULL);
+ path, origin_tag, NULL);
}
/**
g_settings_backend_dispatch_signal (backend,
G_STRUCT_OFFSET (GSettingsListenerVTable,
writable_changed),
- key, NULL, NULL, NULL, NULL);
+ key, NULL, NULL);
}
/**
g_settings_backend_dispatch_signal (backend,
G_STRUCT_OFFSET (GSettingsListenerVTable,
path_writable_changed),
- path, NULL, NULL, NULL, NULL);
+ path, NULL, NULL);
}
typedef struct
* g_settings_backend_get_default:
*
* Returns the default #GSettingsBackend. It is possible to override
- * the default by setting the <envar>GSETTINGS_BACKEND</envar>
- * environment variable to the name of a settings backend.
+ * the default by setting the `GSETTINGS_BACKEND` environment variable
+ * to the name of a settings backend.
*
* The user gets a reference to the backend.
*