[telepathy-mission-control/master] McdDispatcher: add a concept of blocking dispatching until initial clients are ready

Simon McVittie simon.mcvittie at collabora.co.uk
Fri May 15 09:55:50 PDT 2009


This doesn't do actually delay anything yet.
---
 src/mcd-dispatcher.c |   76 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 3c989da..2186cb0 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -202,6 +202,19 @@ 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 has been inspected (1 lock per client
+     *   for Interfaces, + 1 lock per client per subsequent Get/GetAll call)
+     * When nothing more is stopping us from dispatching channels, we start to
+     * do so.
+     * */
+    gsize startup_lock;
+    gboolean startup_completed;
+
     /* Initially FALSE, meaning we suppress OperationList.DispatchOperations
      * change notification signals because nobody has retrieved that property
      * yet. Set to TRUE the first time someone reads the DispatchOperations
@@ -1838,6 +1851,23 @@ mcd_client_set_filters (McdClient *client,
 }
 
 static void
+mcd_dispatcher_release_startup_lock (McdDispatcher *self)
+{
+    if (self->priv->startup_completed)
+        return;
+
+    g_assert (self->priv->startup_lock >= 1);
+
+    self->priv->startup_lock--;
+
+    if (self->priv->startup_lock == 0)
+    {
+        DEBUG ("All initial clients have been inspected");
+        self->priv->startup_completed = TRUE;
+    }
+}
+
+static void
 get_channel_filter_cb (TpProxy *proxy,
                        const GValue *value,
                        const GError *error,
@@ -1854,7 +1884,7 @@ get_channel_filter_cb (TpProxy *proxy,
     {
         DEBUG ("Client %s vanished while we were getting its Client filters",
                bus_name);
-        return;
+        goto finally;
     }
 
     if (error != NULL)
@@ -1862,18 +1892,20 @@ get_channel_filter_cb (TpProxy *proxy,
         DEBUG ("error getting a filter list for client %s: %s #%d: %s",
                tp_proxy_get_object_path (proxy),
                g_quark_to_string (error->domain), error->code, error->message);
-        return;
+        goto finally;
     }
 
     if (!G_VALUE_HOLDS (value, TP_ARRAY_TYPE_STRING_VARIANT_MAP_LIST))
     {
         DEBUG ("wrong type for filter property on client %s: %s",
                tp_proxy_get_object_path (proxy), G_VALUE_TYPE_NAME (value));
-        return;
+        goto finally;
     }
 
     mcd_client_set_filters (client, GPOINTER_TO_UINT (user_data),
                             g_value_get_boxed (value));
+finally:
+    mcd_dispatcher_release_startup_lock (self);
 }
 
 static void
@@ -1893,7 +1925,7 @@ handler_get_all_cb (TpProxy *proxy,
         DEBUG ("GetAll(Handler) for client %s failed: %s #%d: %s",
                bus_name, g_quark_to_string (error->domain), error->code,
                error->message);
-        return;
+        goto finally;
     }
 
     client = g_hash_table_lookup (self->priv->clients, bus_name);
@@ -1902,7 +1934,7 @@ handler_get_all_cb (TpProxy *proxy,
     {
         DEBUG ("Client %s vanished while getting its Handler properties",
                bus_name);
-        return;
+        goto finally;
     }
 
     filters = tp_asv_get_boxed (properties, "HandlerChannelFilter",
@@ -1925,6 +1957,9 @@ handler_get_all_cb (TpProxy *proxy,
                                                   NULL);
     DEBUG ("%s has BypassApproval=%c", client->name,
            client->bypass_approver ? 'T' : 'F');
+
+finally:
+    mcd_dispatcher_release_startup_lock (self);
 }
 
 static void
@@ -1962,14 +1997,14 @@ get_interfaces_cb (TpProxy *proxy,
         DEBUG ("Error getting Interfaces for Client %s, assuming none: "
                "%s %d %s", bus_name,
                g_quark_to_string (error->domain), error->code, error->message);
-        return;
+        goto finally;
     }
 
     if (!G_VALUE_HOLDS (out_Value, G_TYPE_STRV))
     {
         DEBUG ("Wrong type getting Interfaces for Client %s, assuming none: "
                "%s", bus_name, G_VALUE_TYPE_NAME (out_Value));
-        return;
+        goto finally;
     }
 
     client = g_hash_table_lookup (self->priv->clients, bus_name);
@@ -1978,7 +2013,7 @@ get_interfaces_cb (TpProxy *proxy,
     {
         DEBUG ("Client %s vanished while we were getting its interfaces",
                bus_name);
-        return;
+        goto finally;
     }
 
     arr = g_value_get_boxed (out_Value);
@@ -1999,6 +2034,9 @@ get_interfaces_cb (TpProxy *proxy,
     client_add_interface_by_id (client);
     if (client->interfaces & MCD_CLIENT_APPROVER)
     {
+        if (!self->priv->startup_completed)
+            self->priv->startup_lock++;
+
         tp_cli_dbus_properties_call_get
             (client->proxy, -1, MC_IFACE_CLIENT_APPROVER,
              "ApproverChannelFilter", get_channel_filter_cb,
@@ -2006,17 +2044,26 @@ get_interfaces_cb (TpProxy *proxy,
     }
     if (client->interfaces & MCD_CLIENT_HANDLER)
     {
+        if (!self->priv->startup_completed)
+            self->priv->startup_lock++;
+
         tp_cli_dbus_properties_call_get_all
             (client->proxy, -1, MC_IFACE_CLIENT_HANDLER,
              handler_get_all_cb, NULL, NULL, G_OBJECT (self));
     }
     if (client->interfaces & MCD_CLIENT_OBSERVER)
     {
+        if (!self->priv->startup_completed)
+            self->priv->startup_lock++;
+
         tp_cli_dbus_properties_call_get
             (client->proxy, -1, MC_IFACE_CLIENT_OBSERVER,
              "ObserverChannelFilter", get_channel_filter_cb,
              GUINT_TO_POINTER (MCD_CLIENT_OBSERVER), NULL, G_OBJECT (self));
     }
+
+finally:
+    mcd_dispatcher_release_startup_lock (self);
 }
 
 static void
@@ -2200,6 +2247,10 @@ create_mcd_client (McdDispatcher *self,
     if (!file_found)
     {
         DEBUG ("No .client file for %s. Ask on D-Bus.", name);
+
+        if (!self->priv->startup_completed)
+            self->priv->startup_lock++;
+
         tp_cli_dbus_properties_call_get (client->proxy, -1,
             MC_IFACE_CLIENT, "Interfaces", get_interfaces_cb, NULL,
             NULL, G_OBJECT (self));
@@ -2263,6 +2314,9 @@ list_names_cb (TpDBusDaemon *proxy,
     McdDispatcher *self = MCD_DISPATCHER (weak_object);
 
     new_names_cb (self, out0, FALSE);
+
+    /* paired with one of the two locks in _constructed */
+    mcd_dispatcher_release_startup_lock (self);
 }
 
 static void
@@ -2275,6 +2329,9 @@ list_activatable_names_cb (TpDBusDaemon *proxy,
     McdDispatcher *self = MCD_DISPATCHER (weak_object);
 
     new_names_cb (self, out0, TRUE);
+
+    /* paired with one of the two locks in _constructed */
+    mcd_dispatcher_release_startup_lock (self);
 }
 
 static void
@@ -2348,6 +2405,9 @@ mcd_dispatcher_constructed (GObject *object)
     tp_cli_dbus_daemon_call_list_names (priv->dbus_daemon,
         -1, list_names_cb, NULL, NULL, object);
 
+    priv->startup_completed = FALSE;
+    priv->startup_lock = 2;   /* ListNames + ListActivatableNames */
+
     dgc = TP_PROXY (priv->dbus_daemon)->dbus_connection;
 
     if (!_mcd_dbus_daemon_request_name (priv->dbus_daemon,
-- 
1.5.6.5




More information about the telepathy-commits mailing list