[dconf/wip/reorg] Reimplement sync() functionality



commit 4860be9319e971da6a21fe9f0e83a86b2581314e
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue Jul 10 13:58:03 2012 -0400

    Reimplement sync() functionality
    
    Add dconf_engine_sync() that does the same thing as the code in the
    GSettings backend used to do, in a cleaner way.
    
    Update the GSettings backend to use the new call.
    
    Add a new call to DConfClient wrapping the engine call as well.

 client/dconf-client.c            |   26 +++++++++++++++++++++++-
 client/dconf-client.h            |    2 +
 docs/dconf-sections.txt          |    1 +
 engine/dconf-engine.c            |   39 +++++++++++++++++++++++++++++++++++++-
 engine/dconf-engine.h            |    4 +++
 gsettings/dconfsettingsbackend.c |    4 ++-
 6 files changed, 72 insertions(+), 4 deletions(-)
---
diff --git a/client/dconf-client.c b/client/dconf-client.c
index fad445c..7a2a96c 100644
--- a/client/dconf-client.c
+++ b/client/dconf-client.c
@@ -305,7 +305,9 @@ dconf_client_is_writable (DConfClient *client,
  *
  * This call merely queues up the write and returns immediately, without
  * blocking.  The only errors that can be detected or reported at this
- * point are attempts to write to read-only keys.
+ * point are attempts to write to read-only keys.  If the application
+ * exits immediately after this function returns then the queued call
+ * may never be sent; see dconf_client_sync().
  *
  * A local copy of the written value is kept so that calls to
  * dconf_client_read() that occur before the service actually makes the
@@ -393,7 +395,9 @@ dconf_client_write_sync (DConfClient   *client,
  *
  * This call merely queues up the write and returns immediately, without
  * blocking.  The only errors that can be detected or reported at this
- * point are attempts to write to read-only keys.
+ * point are attempts to write to read-only keys.  If the application
+ * exits immediately after this function returns then the queued call
+ * may never be sent; see dconf_client_sync().
  *
  * A local copy of the written value is kept so that calls to
  * dconf_client_read() that occur before the service actually makes the
@@ -546,3 +550,21 @@ dconf_client_unwatch_sync (DConfClient *client,
 
   dconf_engine_unwatch_sync (client->engine, path);
 }
+
+/**
+ * dconf_client_sync:
+ * @client: a #DConfClient
+ *
+ * Blocks until all outstanding "fast" change or write operations have
+ * been submitted to the service.
+ *
+ * Applications should generally call this before exiting on any
+ * #DConfClient that they wrote to.
+ **/
+void
+dconf_client_sync (DConfClient *client)
+{
+  g_return_if_fail (DCONF_IS_CLIENT (client));
+
+  dconf_engine_sync (client->engine);
+}
diff --git a/client/dconf-client.h b/client/dconf-client.h
index d09fdbd..3a606c2 100644
--- a/client/dconf-client.h
+++ b/client/dconf-client.h
@@ -78,6 +78,8 @@ void                    dconf_client_unwatch_fast                       (DConfCl
 void                    dconf_client_unwatch_sync                       (DConfClient          *client,
                                                                          const gchar          *path);
 
+void                    dconf_client_sync                               (DConfClient          *client);
+
 G_END_DECLS
 
 #endif /* __dconf_client_h__ */
diff --git a/docs/dconf-sections.txt b/docs/dconf-sections.txt
index 693ecbc..4f924b7 100644
--- a/docs/dconf-sections.txt
+++ b/docs/dconf-sections.txt
@@ -13,6 +13,7 @@ dconf_client_watch_fast
 dconf_client_watch_sync
 dconf_client_unwatch_fast
 dconf_client_unwatch_sync
+dconf_client_sync
 <SUBSECTION Standard>
 DConfClientClass
 DCONF_CLIENT
diff --git a/engine/dconf-engine.c b/engine/dconf-engine.c
index c1410b6..8d9837a 100644
--- a/engine/dconf-engine.c
+++ b/engine/dconf-engine.c
@@ -161,7 +161,8 @@ struct _DConfEngine
   DConfEngineSource **sources;      /* Array never changes, but each source changes internally. */
   gint                n_sources;
 
-  GMutex              queue_lock;   /* This lock is for pending, in_flight */
+  GMutex              queue_lock;   /* This lock is for pending, in_flight, queue_cond */
+  GCond               queue_cond;   /* Signalled when the queues empty */
   GQueue              pending;      /* DConfChangeset */
   GQueue              in_flight;    /* DConfChangeset */
 
@@ -233,6 +234,7 @@ dconf_engine_new (gpointer       user_data,
 
   g_mutex_init (&engine->sources_lock);
   g_mutex_init (&engine->queue_lock);
+  g_cond_init (&engine->queue_cond);
 
   engine->sources = dconf_engine_profile_open (NULL, &engine->n_sources);
 
@@ -279,6 +281,7 @@ dconf_engine_unref (DConfEngine *engine)
 
       g_mutex_clear (&engine->sources_lock);
       g_mutex_clear (&engine->queue_lock);
+      g_cond_clear (&engine->queue_cond);
 
       g_free (engine->last_handled);
 
@@ -948,6 +951,16 @@ dconf_engine_manage_queue (DConfEngine *engine)
 
       g_queue_push_tail (&engine->in_flight, oc->change);
     }
+
+  if (g_queue_is_empty (&engine->in_flight))
+    {
+      /* The in-flight queue should not be empty if we have changes
+       * pending...
+       */
+      g_assert (g_queue_is_empty (&engine->pending));
+
+      g_cond_broadcast (&engine->queue_cond);
+    }
 }
 
 static gboolean
@@ -1123,3 +1136,27 @@ dconf_engine_handle_dbus_signal (GBusType     type,
       g_warning ("Need to handle writability changes"); /* XXX */
     }
 }
+
+gboolean
+dconf_engine_has_outstanding (DConfEngine *engine)
+{
+  gboolean has;
+
+  /* The in-flight queue will never be empty unless the pending queue is
+   * also empty, so we only really need to check one of them...
+   */
+  dconf_engine_lock_queues (engine);
+  has = !g_queue_is_empty (&engine->in_flight);
+  dconf_engine_unlock_queues (engine);
+
+  return has;
+}
+
+void
+dconf_engine_sync (DConfEngine *engine)
+{
+  dconf_engine_lock_queues (engine);
+  while (!g_queue_is_empty (&engine->in_flight))
+    g_cond_wait (&engine->queue_cond, &engine->queue_lock);
+  dconf_engine_unlock_queues (engine);
+}
diff --git a/engine/dconf-engine.h b/engine/dconf-engine.h
index bad8cf1..96ac42b 100644
--- a/engine/dconf-engine.h
+++ b/engine/dconf-engine.h
@@ -152,6 +152,10 @@ gboolean                dconf_engine_change_sync                        (DConfEn
                                                                          DConfChangeset          *changeset,
                                                                          gchar                  **tag,
                                                                          GError                 **error);
+G_GNUC_INTERNAL
+gboolean                dconf_engine_has_outstanding                    (DConfEngine             *engine);
+G_GNUC_INTERNAL
+void                    dconf_engine_sync                               (DConfEngine             *engine);
 
 /* Asynchronous API: not implemented yet (and maybe never?) */
 
diff --git a/gsettings/dconfsettingsbackend.c b/gsettings/dconfsettingsbackend.c
index 32b2cab..11c123c 100644
--- a/gsettings/dconfsettingsbackend.c
+++ b/gsettings/dconfsettingsbackend.c
@@ -135,7 +135,9 @@ dconf_settings_backend_unsubscribe (GSettingsBackend *backend,
 static void
 dconf_settings_backend_sync (GSettingsBackend *backend)
 {
-  /* XXX implement sync */
+  DConfSettingsBackend *dcsb = (DConfSettingsBackend *) backend;
+
+  dconf_engine_sync (dcsb->engine);
 }
 
 static void



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