[telepathy-mission-control/master] McdDispatchOperation: allow delaying ChannelLost and Finished

Simon McVittie simon.mcvittie at collabora.co.uk
Mon Apr 20 07:13:28 PDT 2009


---
 src/mcd-dispatch-operation-priv.h |    5 ++
 src/mcd-dispatch-operation.c      |   77 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 81 insertions(+), 1 deletions(-)

diff --git a/src/mcd-dispatch-operation-priv.h b/src/mcd-dispatch-operation-priv.h
index b68a177..5d61977 100644
--- a/src/mcd-dispatch-operation-priv.h
+++ b/src/mcd-dispatch-operation-priv.h
@@ -33,6 +33,11 @@ G_GNUC_INTERNAL McdDispatchOperation *_mcd_dispatch_operation_new (
 G_GNUC_INTERNAL void _mcd_dispatch_operation_lose_channel (
     McdDispatchOperation *self, McdChannel *channel, GList **channels);
 
+G_GNUC_INTERNAL void _mcd_dispatch_operation_block_finished (
+    McdDispatchOperation *self);
+G_GNUC_INTERNAL void _mcd_dispatch_operation_unblock_finished (
+    McdDispatchOperation *self);
+
 G_END_DECLS
 
 #endif
diff --git a/src/mcd-dispatch-operation.c b/src/mcd-dispatch-operation.c
index f000155..2dbfa92 100644
--- a/src/mcd-dispatch-operation.c
+++ b/src/mcd-dispatch-operation.c
@@ -75,6 +75,7 @@ struct _McdDispatchOperationPrivate
     gchar *object_path;
     GStrv possible_handlers;
     GHashTable *properties;
+    gsize block_finished;
 
     /* Results */
     guint finished : 1;
@@ -86,7 +87,11 @@ struct _McdDispatchOperationPrivate
 
     McdConnection *connection;
 
+    /* Owned McdChannels we're dispatching */
     GList *channels;
+    /* Owned McdChannels for which we can't emit ChannelLost yet, in
+     * reverse chronological order */
+    GList *lost_channels;
 };
 
 enum
@@ -200,7 +205,11 @@ mcd_dispatch_operation_finish (McdDispatchOperation *operation)
     McdDispatchOperationPrivate *priv = operation->priv;
 
     priv->finished = TRUE;
-    mc_svc_channel_dispatch_operation_emit_finished (operation);
+
+    if (priv->block_finished == 0)
+    {
+        mc_svc_channel_dispatch_operation_emit_finished (operation);
+    }
 }
 
 static void
@@ -624,6 +633,14 @@ _mcd_dispatch_operation_lose_channel (McdDispatchOperation *self,
         g_critical ("McdChannel has already lost its TpChannel: %p",
             channel);
     }
+    else if (self->priv->block_finished)
+    {
+        /* We're still invoking approvers, so we're not allowed to talk
+         * about it right now. Instead, save the signal for later. */
+        self->priv->lost_channels =
+            g_list_prepend (self->priv->lost_channels,
+                            g_object_ref (channel));
+    }
     else
     {
         const GError *error = mcd_channel_get_error (channel);
@@ -647,3 +664,61 @@ _mcd_dispatch_operation_lose_channel (McdDispatchOperation *self,
         }
     }
 }
+
+void
+_mcd_dispatch_operation_block_finished (McdDispatchOperation *self)
+{
+    g_return_if_fail (MCD_IS_DISPATCH_OPERATION (self));
+    g_return_if_fail (!self->priv->finished);
+
+    self->priv->block_finished++;
+}
+
+void
+_mcd_dispatch_operation_unblock_finished (McdDispatchOperation *self)
+{
+    g_return_if_fail (MCD_IS_DISPATCH_OPERATION (self));
+    g_return_if_fail (self->priv->block_finished > 0);
+
+    self->priv->block_finished--;
+
+    if (self->priv->block_finished == 0)
+    {
+        GList *lost_channels;
+
+        /* get the lost channels into chronological order, and steal them from
+         * the object*/
+        lost_channels = g_list_reverse (self->priv->lost_channels);
+        self->priv->lost_channels = NULL;
+
+        while (lost_channels != NULL)
+        {
+            McdChannel *channel = lost_channels->data;
+            const gchar *object_path = mcd_channel_get_object_path (channel);
+
+            if (object_path == NULL)
+            {
+                /* This shouldn't happen, but McdChannel is twisty enough
+                 * that I can't be sure */
+                g_critical ("McdChannel has already lost its TpChannel: %p",
+                    channel);
+            }
+            else
+            {
+                const GError *error = mcd_channel_get_error (channel);
+                gchar *error_name = _mcd_build_error_string (error);
+
+                mc_svc_channel_dispatch_operation_emit_channel_lost (self,
+                    object_path, error_name, error->message);
+                g_free (error_name);
+            }
+
+            lost_channels = g_list_delete_link (lost_channels, lost_channels);
+        }
+
+        if (self->priv->finished)
+        {
+            mc_svc_channel_dispatch_operation_emit_finished (self);
+        }
+    }
+}
-- 
1.5.6.5




More information about the telepathy-commits mailing list