[glib/wip/settings-backend: 2/7] GSettings: remove main context logic from backend



commit b4187cfa1a60b80dbe2083abf7c1c57aa8ee5ef9
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Dec 29 02:57:58 2011 -0500

    GSettings: remove main context logic from backend
    
    The main context dispatching logic substantially complicates the backend
    and is only needed for the GSettings frontend.  Move it there instead.

 gio/gdelayedsettingsbackend.c  |    3 +-
 gio/gsettings.c                |   82 +++++++++++++++++++++++++--------------
 gio/gsettingsbackend.c         |   75 ++----------------------------------
 gio/gsettingsbackendinternal.h |    3 +-
 4 files changed, 58 insertions(+), 105 deletions(-)
---
diff --git a/gio/gdelayedsettingsbackend.c b/gio/gdelayedsettingsbackend.c
index b85d724..a891fe1 100644
--- a/gio/gdelayedsettingsbackend.c
+++ b/gio/gdelayedsettingsbackend.c
@@ -347,8 +347,7 @@ g_delayed_settings_backend_new (GSettingsBackend *backend,
 
   g_object_weak_ref (owner, g_delayed_settings_backend_disown, delayed);
 
-  g_settings_backend_watch (delayed->priv->backend,
-                            g_delayed_settings_got_event, G_OBJECT (delayed), NULL);
+  g_settings_backend_watch (delayed->priv->backend, g_delayed_settings_got_event, G_OBJECT (delayed));
 
   return delayed;
 }
diff --git a/gio/gsettings.c b/gio/gsettings.c
index 619d5a5..659f264 100644
--- a/gio/gsettings.c
+++ b/gio/gsettings.c
@@ -294,16 +294,22 @@ g_settings_real_writable_change_event (GSettings *settings,
   return FALSE;
 }
 
-static void
-g_settings_emit_signal (GSettings          *settings,
-                        GSettingsEventType  type,
-                        const GQuark       *quarks,
-                        gint                n_items)
+typedef struct
+{
+  GSettings          *settings;
+  GSettingsEventType  type;
+  GQuark             *quarks;
+  gint                n_items;
+} GSettingsSignalData;
+
+static gboolean
+g_settings_emit_signal (gpointer user_data)
 {
+  GSettingsSignalData *data = user_data;
   gboolean ignore_this;
   guint signal_id;
 
-  switch (type)
+  switch (data->type)
     {
     case G_SETTINGS_EVENT_CHANGE:
       signal_id = g_settings_signals[SIGNAL_CHANGE_EVENT];
@@ -317,23 +323,49 @@ g_settings_emit_signal (GSettings          *settings,
       g_assert_not_reached ();
     }
 
-  /* writable-change-event signals are emitted in a different way */
+  /* this signal is presently emitted differently */
   if (signal_id == g_settings_signals[SIGNAL_WRITABLE_CHANGE_EVENT])
     {
-      if (n_items > 0)
+      if (data->n_items > 0)
         {
           gint i;
 
-          for (i = 0; i < n_items; i++)
-            g_signal_emit (settings, signal_id, 0, quarks[i], &ignore_this);
+          for (i = 0; i < data->n_items; i++)
+            g_signal_emit (data->settings, signal_id, 0, data->quarks[i], &ignore_this);
         }
       else
-        g_signal_emit (settings, signal_id, 0, (GQuark) 0, &ignore_this);
+        g_signal_emit (data->settings, signal_id, 0, (GQuark) 0, &ignore_this);
 
-      return;
+      goto out;
     }
 
-  g_signal_emit (settings, signal_id, 0, quarks, n_items, &ignore_this);
+  g_signal_emit (data->settings, signal_id, 0, data->quarks, data->n_items, &ignore_this);
+
+out:
+  g_object_unref (data->settings);
+  g_free (data->quarks);
+
+  g_slice_free (GSettingsSignalData, data);
+
+  return G_SOURCE_REMOVE;
+}
+
+/* consumes 'quarks' */
+static void
+g_settings_dispatch_signal (GSettings          *settings,
+                            GSettingsEventType  type,
+                            GQuark             *quarks,
+                            gint                n_items)
+{
+  GSettingsSignalData *data;
+
+  data = g_slice_new (GSettingsSignalData);
+  data->settings = g_object_ref (settings);
+  data->type = type;
+  data->quarks = quarks;
+  data->n_items = n_items;
+
+  g_main_context_invoke (settings->priv->main_context, g_settings_emit_signal, data);
 }
 
 static void
@@ -403,7 +435,7 @@ g_settings_got_event (GObject              *target,
           GQuark quark;
 
           quark = g_quark_from_string (prefix);
-          g_settings_emit_signal (settings, event->type, &quark, 1);
+          g_settings_dispatch_signal (settings, event->type, g_memdup (&quark, sizeof quark), 1);
         }
     }
   else
@@ -421,7 +453,7 @@ g_settings_got_event (GObject              *target,
        * this case since everything has changed.
        */
       if (event->keys[0] == NULL)
-        g_settings_emit_signal (settings, event->type, NULL, 0);
+        g_settings_dispatch_signal (settings, event->type, NULL, 0);
 
       else
         {
@@ -429,11 +461,7 @@ g_settings_got_event (GObject              *target,
           gint n, i, j;
 
           n = g_strv_length (event->keys);
-
-          if (20 < n)
-            quarks = g_new (GQuark, n);
-          else
-            quarks = g_newa (GQuark, n);
+          quarks = g_new (GQuark, n);
 
           j = 0;
           for (i = 0; event->keys[i]; i++)
@@ -458,9 +486,8 @@ g_settings_got_event (GObject              *target,
 
           /* Only signal if we actually had a match. */
           if (j > 0)
-            g_settings_emit_signal (settings, event->type, quarks, j);
-
-          if (20 < n)
+            g_settings_dispatch_signal (settings, event->type, quarks, j);
+          else
             g_free (quarks);
         }
     }
@@ -600,10 +627,7 @@ g_settings_constructed (GObject *object)
   if (settings->priv->backend == NULL)
     settings->priv->backend = g_settings_backend_get_default ();
 
-  g_settings_backend_watch (settings->priv->backend,
-                            g_settings_got_event,
-                            G_OBJECT (settings),
-                            settings->priv->main_context);
+  g_settings_backend_watch (settings->priv->backend, g_settings_got_event, G_OBJECT (settings));
   g_settings_backend_subscribe (settings->priv->backend,
                                 settings->priv->path);
 }
@@ -1927,9 +1951,7 @@ g_settings_delay (GSettings *settings)
   g_object_unref (settings->priv->backend);
 
   settings->priv->backend = G_SETTINGS_BACKEND (settings->priv->delayed);
-  g_settings_backend_watch (settings->priv->backend,
-                            g_settings_got_event, G_OBJECT (settings),
-                            settings->priv->main_context);
+  g_settings_backend_watch (settings->priv->backend, g_settings_got_event, G_OBJECT (settings));
 
   g_object_notify (G_OBJECT (settings), "delay-apply");
 }
diff --git a/gio/gsettingsbackend.c b/gio/gsettingsbackend.c
index 62235d4..c09bba8 100644
--- a/gio/gsettingsbackend.c
+++ b/gio/gsettingsbackend.c
@@ -35,7 +35,6 @@
 
 G_DEFINE_ABSTRACT_TYPE (GSettingsBackend, g_settings_backend, G_TYPE_OBJECT)
 
-typedef struct _GSettingsBackendClosure GSettingsBackendClosure;
 typedef struct _GSettingsBackendWatch   GSettingsBackendWatch;
 
 struct _GSettingsBackendPrivate
@@ -128,18 +127,9 @@ struct _GSettingsBackendWatch
 {
   GObject               *target;
   GSettingsEventFunc     function;
-  GMainContext          *context;
   GSettingsBackendWatch *next;
 };
 
-struct _GSettingsBackendClosure
-{
-  GSettingsEventFunc  function;
-  GSettingsBackend   *backend;
-  GObject            *target;
-  GSettingsEvent      event;
-};
-
 static void
 g_settings_backend_watch_weak_notify (gpointer  data,
                                       GObject  *where_the_object_was)
@@ -169,31 +159,14 @@ 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
  * ...: callbacks...
  *
  * Registers a new watch on a #GSettingsBackend.
- *
- * note: %NULL @context does not mean "default main context" but rather,
- * "it is okay to dispatch in any context".  If the default main context
- * is specifically desired then it must be given.
- *
- * note also: if you want to get meaningful values for the @origin_tag
- * that appears as an argument to some of the callbacks, you *must* have
- * @context as %NULL.  Otherwise, you are subject to cross-thread
- * dispatching and whatever owned @origin_tag at the time that the event
- * occurred may no longer own it.  This is a problem if you consider that
- * you may now be the new owner of that address and mistakenly think
- * that the event in question originated from yourself.
- *
- * tl;dr: If you give a non-%NULL @context then you must ignore the
- * value of @origin_tag given to any callbacks.
  **/
 void
 g_settings_backend_watch (GSettingsBackend   *backend,
                           GSettingsEventFunc  callback,
-                          GObject            *target,
-                          GMainContext       *context)
+                          GObject            *target)
 {
   GSettingsBackendWatch *watch;
 
@@ -220,19 +193,11 @@ 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.
-   *
    * All access to the list holds a mutex.  We have some strategies to
    * avoid some of the pain that would be associated with that.
    */
 
   watch = g_slice_new (GSettingsBackendWatch);
-  watch->context = context;
   watch->function = callback;
   watch->target = target;
   g_object_weak_ref (target, g_settings_backend_watch_weak_notify, backend);
@@ -255,23 +220,6 @@ g_settings_backend_unwatch (GSettingsBackend *backend,
   g_settings_backend_watch_weak_notify (backend, target);
 }
 
-static gboolean
-g_settings_backend_invoke_closure (gpointer user_data)
-{
-  GSettingsBackendClosure *closure = user_data;
-
-  closure->function (closure->target, &closure->event);
-
-  g_object_unref (closure->backend);
-  g_object_unref (closure->target);
-  g_strfreev (closure->event.keys);
-  g_free (closure->event.prefix);
-
-  g_slice_free (GSettingsBackendClosure, closure);
-
-  return FALSE;
-}
-
 void
 g_settings_backend_report_event (GSettingsBackend     *backend,
                                  const GSettingsEvent *event)
@@ -301,28 +249,13 @@ g_settings_backend_report_event (GSettingsBackend     *backend,
   /* The suffix is now immutable, so this is safe. */
   for (watch = suffix; watch; watch = next)
     {
-      GSettingsBackendClosure *closure;
-
-      closure = g_slice_new (GSettingsBackendClosure);
-      closure->backend = g_object_ref (backend);
-      closure->target = watch->target; /* we took our ref above */
-      closure->function = watch->function;
-      closure->event.type = event->type;
-      closure->event.prefix = g_strdup (event->prefix);
-      closure->event.keys = g_strdupv (event->keys);
-      closure->event.origin_tag = event->origin_tag;
-
       /* 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).
+       * iteration of the loop (since we unref the target below).
        */
       next = watch->next;
 
-      if (watch->context)
-        g_main_context_invoke (watch->context,
-                               g_settings_backend_invoke_closure,
-                               closure);
-      else
-        g_settings_backend_invoke_closure (closure);
+      watch->function (watch->target, event);
+      g_object_unref (watch->target); /* free the ref we acquired above */
     }
 }
 
diff --git a/gio/gsettingsbackendinternal.h b/gio/gsettingsbackendinternal.h
index 288b3b4..0587cab 100644
--- a/gio/gsettingsbackendinternal.h
+++ b/gio/gsettingsbackendinternal.h
@@ -32,8 +32,7 @@ typedef void         (* GSettingsEventFunc)                             (GObject
 G_GNUC_INTERNAL
 void                    g_settings_backend_watch                        (GSettingsBackend     *backend,
                                                                          GSettingsEventFunc    callback,
-                                                                         GObject              *target,
-                                                                         GMainContext         *context);
+                                                                         GObject              *target);
 G_GNUC_INTERNAL
 void                    g_settings_backend_unwatch                      (GSettingsBackend     *backend,
                                                                          GObject              *target);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]