[telepathy-mission-control/master] McdClientProxy: manage startup locks here, emitting ready when finished

Simon McVittie simon.mcvittie at collabora.co.uk
Mon Oct 19 07:01:11 PDT 2009


---
 src/client-registry.c |   60 +++++++++++++++++++++++++++++
 src/client-registry.h |    8 ++++
 src/mcd-dispatcher.c  |   99 ++++++++++++++----------------------------------
 3 files changed, 97 insertions(+), 70 deletions(-)

diff --git a/src/client-registry.c b/src/client-registry.c
index 38cfd39..d925a04 100644
--- a/src/client-registry.c
+++ b/src/client-registry.c
@@ -23,6 +23,8 @@
 
 #include <telepathy-glib/handle-repo-dynamic.h>
 
+#include "mcd-debug.h"
+
 G_DEFINE_TYPE (McdClientRegistry, _mcd_client_registry, G_TYPE_OBJECT)
 
 enum
@@ -51,8 +53,56 @@ struct _McdClientRegistryPrivate
   /* Not really handles as such, but TpHandleRepoIface gives us a convenient
    * reference-counted string pool */
   TpHandleRepoIface *string_pool;
+
+  /* We don't want to start dispatching until startup has finished. This
+   * is defined as:
+   * - activatable clients have been enumerated (ListActivatableNames)
+   *   (1 lock)
+   * - running clients have been enumerated (ListNames) (1 lock)
+   * - each client found that way is ready (1 lock per client)
+   * When nothing more is stopping us from dispatching channels, we signal
+   * ready.
+   * */
+  gsize startup_lock;
+  gboolean startup_completed;
 };
 
+void
+_mcd_client_registry_inc_startup_lock (McdClientRegistry *self)
+{
+  g_return_if_fail (MCD_IS_CLIENT_REGISTRY (self));
+
+  if (!self->priv->startup_completed)
+    {
+      DEBUG ("%" G_GSIZE_FORMAT " -> %" G_GSIZE_FORMAT,
+          self->priv->startup_lock, self->priv->startup_lock + 1);
+      g_return_if_fail (self->priv->startup_lock > 0);
+      self->priv->startup_lock++;
+    }
+}
+
+void
+_mcd_client_registry_dec_startup_lock (McdClientRegistry *self)
+{
+  g_return_if_fail (MCD_IS_CLIENT_REGISTRY (self));
+
+  if (self->priv->startup_completed)
+    return;
+
+  DEBUG ("%" G_GSIZE_FORMAT " -> %" G_GSIZE_FORMAT,
+      self->priv->startup_lock, self->priv->startup_lock - 1);
+
+  g_return_if_fail (self->priv->startup_lock > 0);
+
+  self->priv->startup_lock--;
+
+  if (self->priv->startup_lock == 0)
+    {
+      self->priv->startup_completed = TRUE;
+      g_signal_emit (self, signals[S_READY], 0);
+    }
+}
+
 static void mcd_client_registry_gone_cb (McdClientProxy *client,
     McdClientRegistry *self);
 
@@ -129,6 +179,9 @@ _mcd_client_registry_init (McdClientRegistry *self)
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MCD_TYPE_CLIENT_REGISTRY,
       McdClientRegistryPrivate);
 
+  self->priv->startup_completed = FALSE;
+  /* the ListNames call we'll make in _constructed is the initial lock */
+  self->priv->startup_lock = 1;
   self->priv->clients = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
       g_object_unref);
 }
@@ -291,3 +344,10 @@ _mcd_client_registry_dup_client_caps (McdClientRegistry *self)
 
   return vas;
 }
+
+gboolean
+_mcd_client_registry_is_ready (McdClientRegistry *self)
+{
+  g_return_val_if_fail (MCD_IS_CLIENT_REGISTRY (self), FALSE);
+  return self->priv->startup_completed;
+}
diff --git a/src/client-registry.h b/src/client-registry.h
index ef3ac02..3093f0b 100644
--- a/src/client-registry.h
+++ b/src/client-registry.h
@@ -72,6 +72,9 @@ G_GNUC_INTERNAL McdClientProxy *_mcd_client_registry_lookup (
 G_GNUC_INTERNAL GPtrArray *_mcd_client_registry_dup_client_caps (
     McdClientRegistry *self);
 
+G_GNUC_INTERNAL gboolean _mcd_client_registry_is_ready (
+    McdClientRegistry *self);
+
 /* Temporary API for porting */
 
 G_GNUC_INTERNAL McdClientProxy *_mcd_client_registry_add_new (
@@ -80,6 +83,11 @@ G_GNUC_INTERNAL McdClientProxy *_mcd_client_registry_add_new (
 G_GNUC_INTERNAL void _mcd_client_registry_init_hash_iter (
     McdClientRegistry *self, GHashTableIter *iter);
 
+G_GNUC_INTERNAL void _mcd_client_registry_inc_startup_lock (
+    McdClientRegistry *self);
+G_GNUC_INTERNAL void _mcd_client_registry_dec_startup_lock (
+    McdClientRegistry *self);
+
 G_END_DECLS
 
 #endif
diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 7ce8971..e549792 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -173,18 +173,6 @@ struct _McdDispatcherPrivate
 
     McdMaster *master;
 
-    /* We don't want to start dispatching until startup has finished. This
-     * is defined as:
-     * - activatable clients have been enumerated (ListActivatableNames)
-     *   (1 lock)
-     * - running clients have been enumerated (ListNames) (1 lock)
-     * - each client found that way is ready (1 lock per client)
-     * When nothing more is stopping us from dispatching channels, we start to
-     * do so.
-     * */
-    gsize startup_lock;
-    gboolean startup_completed;
-
     /* connection => itself, borrowed */
     GHashTable *connections;
 
@@ -1768,14 +1756,13 @@ mcd_dispatcher_client_gone_cb (McdClientProxy *client,
 }
 
 static void
-mcd_dispatcher_client_added_cb (McdClientRegistry *clients G_GNUC_UNUSED,
+mcd_dispatcher_client_added_cb (McdClientRegistry *clients,
                                 McdClientProxy *client,
                                 McdDispatcher *self)
 {
     /* paired with one in mcd_dispatcher_client_ready_cb, when the
      * McdClientProxy is ready */
-    if (!self->priv->startup_completed)
-        self->priv->startup_lock++;
+    _mcd_client_registry_inc_startup_lock (clients);
 
     g_signal_connect (client, "ready",
                       G_CALLBACK (mcd_dispatcher_client_ready_cb),
@@ -1796,10 +1783,25 @@ mcd_dispatcher_client_added_cb (McdClientRegistry *clients G_GNUC_UNUSED,
 
 static void
 mcd_dispatcher_client_registry_ready_cb (McdClientRegistry *clients,
-                                         McdClientProxy *client,
                                          McdDispatcher *self)
 {
-    DEBUG ("client registry ready");
+    GHashTableIter iter;
+    gpointer p;
+    GPtrArray *vas;
+
+    DEBUG ("All initial clients have been inspected");
+
+    vas = _mcd_client_registry_dup_client_caps (clients);
+
+    g_hash_table_iter_init (&iter, self->priv->connections);
+
+    while (g_hash_table_iter_next (&iter, &p, NULL))
+    {
+        _mcd_connection_start_dispatching (p, vas);
+    }
+
+    g_ptr_array_foreach (vas, (GFunc) g_value_array_free, NULL);
+    g_ptr_array_free (vas, TRUE);
 }
 
 static void
@@ -1860,48 +1862,6 @@ _mcd_dispatcher_dispose (GObject * object)
 }
 
 static void
-mcd_dispatcher_release_startup_lock (McdDispatcher *self)
-{
-    if (self->priv->startup_completed)
-        return;
-
-    /* If we haven't started to dispatch channels, and now we're
-     * self-destructing, we certainly don't want to start dispatching channels
-     * to whatever's left of our handlers. */
-    if (self->priv->is_disposed)
-        return;
-
-    DEBUG ("%p (decrementing from %" G_GSIZE_FORMAT ")",
-           self, self->priv->startup_lock);
-
-    g_assert (self->priv->startup_lock >= 1);
-
-    self->priv->startup_lock--;
-
-    if (self->priv->startup_lock == 0)
-    {
-        GHashTableIter iter;
-        gpointer p;
-        GPtrArray *vas;
-
-        DEBUG ("All initial clients have been inspected");
-        self->priv->startup_completed = TRUE;
-
-        vas = _mcd_client_registry_dup_client_caps (self->priv->clients);
-
-        g_hash_table_iter_init (&iter, self->priv->connections);
-
-        while (g_hash_table_iter_next (&iter, &p, NULL))
-        {
-            _mcd_connection_start_dispatching (p, vas);
-        }
-
-        g_ptr_array_foreach (vas, (GFunc) g_value_array_free, NULL);
-        g_ptr_array_free (vas, TRUE);
-    }
-}
-
-static void
 mcd_dispatcher_update_client_caps (McdDispatcher *self,
                                    McdClientProxy *client)
 {
@@ -1914,7 +1874,7 @@ mcd_dispatcher_update_client_caps (McdDispatcher *self,
      *
      * If we don't have any connections, on the other hand, then there's
      * nothing to do. */
-    if (!self->priv->startup_completed
+    if (!_mcd_client_registry_is_ready (self->priv->clients)
         || g_hash_table_size (self->priv->connections) == 0)
     {
         return;
@@ -1945,7 +1905,7 @@ mcd_dispatcher_client_ready_cb (McdClientProxy *client,
                                           dispatcher);
 
     /* paired with the one in mcd_dispatcher_client_added_cb */
-    mcd_dispatcher_release_startup_lock (dispatcher);
+    _mcd_client_registry_dec_startup_lock (dispatcher->priv->clients);
 }
 
 /* Check the list of strings whether they are valid well-known names of
@@ -2028,8 +1988,8 @@ list_activatable_names_cb (TpDBusDaemon *proxy,
         }
     }
 
-    /* paired with the lock taken in _constructed */
-    mcd_dispatcher_release_startup_lock (self);
+    /* paired with the lock taken when the McdClientRegistry was constructed */
+    _mcd_client_registry_dec_startup_lock (self->priv->clients);
 }
 
 static void
@@ -2048,7 +2008,7 @@ reload_config_cb (TpDBusDaemon *proxy,
 
     tp_cli_dbus_daemon_call_list_activatable_names (self->priv->dbus_daemon,
         -1, list_activatable_names_cb, NULL, NULL, weak_object);
-    /* deliberately not calling mcd_dispatcher_release_startup_lock here -
+    /* deliberately not calling _mcd_client_registry_dec_startup_lock here -
      * this function is "lock-neutral", similarly to list_names_cb (we would
      * take a lock for ListActivatableNames then release the one used for
      * ReloadConfig), so simplify by doing nothing */
@@ -2085,7 +2045,7 @@ list_names_cb (TpDBusDaemon *proxy,
      * installed .service files on its own. */
     tp_cli_dbus_daemon_call_reload_config (self->priv->dbus_daemon, -1,
         reload_config_cb, NULL, NULL, weak_object);
-    /* deliberately not calling mcd_dispatcher_release_startup_lock here -
+    /* deliberately not calling _mcd_client_registry_dec_startup_lock here -
      * this function is "lock-neutral" (we would take a lock for ReloadConfig
      * then release the one used for ListNames), so simplify by doing
      * nothing */
@@ -2152,8 +2112,6 @@ mcd_dispatcher_constructed (GObject *object)
                       object);
 
     DEBUG ("Starting to look for clients");
-    priv->startup_completed = FALSE;
-    priv->startup_lock = 1;   /* the ListNames call we're about to make */
 
     tp_cli_dbus_daemon_connect_to_name_owner_changed (priv->dbus_daemon,
         name_owner_changed_cb, NULL, NULL, object, NULL);
@@ -3153,7 +3111,8 @@ _mcd_dispatcher_recover_channel (McdDispatcher *dispatcher,
      */
     g_return_if_fail (MCD_IS_DISPATCHER (dispatcher));
     priv = dispatcher->priv;
-    g_return_if_fail (priv->startup_completed);
+    g_return_if_fail (_mcd_client_registry_is_ready (
+        dispatcher->priv->clients));
 
     path = mcd_channel_get_object_path (channel);
     unique_name = _mcd_handler_map_get_handler (priv->handler_map, path);
@@ -3336,7 +3295,7 @@ _mcd_dispatcher_dup_client_caps (McdDispatcher *self)
     g_return_val_if_fail (MCD_IS_DISPATCHER (self), NULL);
 
     /* if we're not ready, return NULL to tell the connection not to preload */
-    if (!self->priv->startup_completed)
+    if (!_mcd_client_registry_is_ready (self->priv->clients))
     {
         return NULL;
     }
@@ -3357,7 +3316,7 @@ _mcd_dispatcher_add_connection (McdDispatcher *self,
     g_object_weak_ref ((GObject *) connection, mcd_dispatcher_lost_connection,
                        g_object_ref (self));
 
-    if (self->priv->startup_completed)
+    if (_mcd_client_registry_is_ready (self->priv->clients))
     {
         GPtrArray *vas =
             _mcd_client_registry_dup_client_caps (self->priv->clients);
-- 
1.5.6.5




More information about the telepathy-commits mailing list