X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsettingsbackend.c;h=f211e2cbf095f4812916017f6741c7f8d542985f;hb=5463c8cedbdf9ea2829f83c53876f21b34f57250;hp=6075d7fd048f3b1442d7bc8ecbbdaa81b77c5ec3;hpb=d85b722734a6fcfe94032f6113de9e5c190fd7c3;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gsettingsbackend.c b/gio/gsettingsbackend.c index 6075d7f..f211e2c 100644 --- a/gio/gsettingsbackend.c +++ b/gio/gsettingsbackend.c @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . * * Authors: Ryan Lortie * Matthias Clasen @@ -33,8 +31,6 @@ #include -G_DEFINE_ABSTRACT_TYPE (GSettingsBackend, g_settings_backend, G_TYPE_OBJECT) - typedef struct _GSettingsBackendClosure GSettingsBackendClosure; typedef struct _GSettingsBackendWatch GSettingsBackendWatch; @@ -44,6 +40,8 @@ struct _GSettingsBackendPrivate GMutex lock; }; +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GSettingsBackend, g_settings_backend, G_TYPE_OBJECT) + /* For g_settings_backend_sync_default(), we only want to actually do * the sync if the backend already exists. This avoids us creating an * entire GSettingsBackend in order to call a do-nothing sync() @@ -77,13 +75,11 @@ static gboolean g_settings_has_backend; * g_settings_backend_create_tree() is a convenience function to create * suitable trees. * - * - * The #GSettingsBackend API is exported to allow third-party + * The GSettingsBackend API is exported to allow third-party * 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 - * gio/gsettingsbackend.h - * + * C preprocessor symbol %G_SETTINGS_ENABLE_BACKEND before including + * `gio/gsettingsbackend.h`. **/ static gboolean @@ -134,18 +130,18 @@ struct _GSettingsBackendWatch 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 @@ -177,7 +173,7 @@ g_settings_backend_watch_weak_notify (gpointer data, * g_settings_backend_watch: * @backend: a #GSettingsBackend * @target: the GObject (typically GSettings instance) to call back to - * @context: a #GMainContext, or %NULL + * @context: (allow-none): a #GMainContext, or %NULL * ...: callbacks... * * Registers a new watch on a #GSettingsBackend. @@ -269,11 +265,11 @@ g_settings_backend_invoke_closure (gpointer user_data) 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); @@ -281,80 +277,55 @@ g_settings_backend_invoke_closure (gpointer user_data) 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); + + while (closures) + { + GSettingsBackendClosure *closure = closures->data; - if (watch->context) - g_main_context_invoke (watch->context, + 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); } } @@ -400,7 +371,7 @@ g_settings_backend_changed (GSettingsBackend *backend, g_settings_backend_dispatch_signal (backend, G_STRUCT_OFFSET (GSettingsListenerVTable, changed), - key, origin_tag, NULL, NULL, NULL); + key, origin_tag, NULL); } /** @@ -449,10 +420,7 @@ g_settings_backend_keys_changed (GSettingsBackend *backend, 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); } /** @@ -496,7 +464,7 @@ g_settings_backend_path_changed (GSettingsBackend *backend, g_settings_backend_dispatch_signal (backend, G_STRUCT_OFFSET (GSettingsListenerVTable, path_changed), - path, origin_tag, NULL, NULL, NULL); + path, origin_tag, NULL); } /** @@ -521,7 +489,7 @@ g_settings_backend_writable_changed (GSettingsBackend *backend, g_settings_backend_dispatch_signal (backend, G_STRUCT_OFFSET (GSettingsListenerVTable, writable_changed), - key, NULL, NULL, NULL, NULL); + key, NULL, NULL); } /** @@ -547,7 +515,7 @@ g_settings_backend_path_writable_changed (GSettingsBackend *backend, g_settings_backend_dispatch_signal (backend, G_STRUCT_OFFSET (GSettingsListenerVTable, path_writable_changed), - path, NULL, NULL, NULL, NULL); + path, NULL, NULL); } typedef struct @@ -746,6 +714,43 @@ g_settings_backend_read (GSettingsBackend *backend, } /*< private > + * g_settings_backend_read_user_value: + * @backend: a #GSettingsBackend implementation + * @key: the key to read + * @expected_type: a #GVariantType + * + * Reads the 'user value' of a key. + * + * This is the value of the key that the user has control over and has + * set for themselves. Put another way: if the user did not set the + * value for themselves, then this will return %NULL (even if the + * sysadmin has provided a default value). + * + * Returns: the value that was read, or %NULL + */ +GVariant * +g_settings_backend_read_user_value (GSettingsBackend *backend, + const gchar *key, + const GVariantType *expected_type) +{ + GVariant *value; + + value = G_SETTINGS_BACKEND_GET_CLASS (backend) + ->read_user_value (backend, key, expected_type); + + if (value != NULL) + value = g_variant_take_ref (value); + + if G_UNLIKELY (value && !g_variant_is_of_type (value, expected_type)) + { + g_variant_unref (value); + value = NULL; + } + + return value; +} + +/*< private > * g_settings_backend_write: * @backend: a #GSettingsBackend implementation * @key: the name of the key @@ -772,14 +777,20 @@ g_settings_backend_write (GSettingsBackend *backend, GVariant *value, gpointer origin_tag) { - return G_SETTINGS_BACKEND_GET_CLASS (backend) + gboolean success; + + g_variant_ref_sink (value); + success = G_SETTINGS_BACKEND_GET_CLASS (backend) ->write (backend, key, value, origin_tag); + g_variant_unref (value); + + return success; } /*< private > - * g_settings_backend_write_keys: + * g_settings_backend_write_tree: * @backend: a #GSettingsBackend implementation - * @values: a #GTree containing key-value pairs to write + * @tree: a #GTree containing key-value pairs to write * @origin_tag: the origin tag * * Writes one or more keys. This call will never block. @@ -897,12 +908,18 @@ ignore_subscription (GSettingsBackend *backend, { } +static GVariant * +g_settings_backend_real_read_user_value (GSettingsBackend *backend, + const gchar *key, + const GVariantType *expected_type) +{ + return g_settings_backend_read (backend, key, expected_type, FALSE); +} + static void g_settings_backend_init (GSettingsBackend *backend) { - backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, - G_TYPE_SETTINGS_BACKEND, - GSettingsBackendPrivate); + backend->priv = g_settings_backend_get_instance_private (backend); g_mutex_init (&backend->priv->lock); } @@ -914,9 +931,9 @@ g_settings_backend_class_init (GSettingsBackendClass *class) class->subscribe = ignore_subscription; class->unsubscribe = ignore_subscription; - gobject_class->finalize = g_settings_backend_finalize; + class->read_user_value = g_settings_backend_real_read_user_value; - g_type_class_add_private (class, sizeof (GSettingsBackendPrivate)); + gobject_class->finalize = g_settings_backend_finalize; } static void @@ -962,8 +979,8 @@ g_settings_backend_verify (gpointer impl) * g_settings_backend_get_default: * * Returns the default #GSettingsBackend. It is possible to override - * the default by setting the GSETTINGS_BACKEND - * 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. *