[telepathy-mission-control/master] McdDispatcherContext: separate pending approvers out from client_locks into awaiting_approval and approvers_pending

Simon McVittie simon.mcvittie at collabora.co.uk
Tue Sep 8 08:16:58 PDT 2009


---
 src/mcd-dispatcher.c |   66 +++++++++++++++++++++++++++++++-------------------
 1 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 946c9ea..d3d4c6d 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -99,6 +99,9 @@ struct _McdDispatcherContext
      * phase should be skipped */
     guint skip_approval : 1;
 
+    /* If TRUE, at least one Approver has accepted the CDO. */
+    guint awaiting_approval : 1;
+
     McdDispatcher *dispatcher;
 
     GList *channels;
@@ -112,15 +115,16 @@ struct _McdDispatcherContext
      * Until they have done so, we can't allow the dispatch operation to
      * finish. */
     gsize observers_pending;
+    /* The number of approvers that have not yet returned from
+     * AddDispatchOperation. Until they have done so, we can't allow the
+     * dispatch operation to finish. */
+    gsize approvers_pending;
     /* This variable is the count of locks that must be removed before handlers
      * can be invoked, for reasons other than invoking observers.
      * When the variable gets back to 0 and observers_pending is also 0,
      * handlers are run. */
     gint client_locks;
 
-    /* Number of approvers that we invoked */
-    gint approvers_invoked;
-
     gchar *protocol;
 
     /* State-machine internal data fields: */
@@ -1012,7 +1016,10 @@ finally:
 static void
 mcd_dispatcher_context_check_client_locks (McdDispatcherContext *context)
 {
-    if (context->client_locks == 0 && context->observers_pending == 0)
+    if (context->client_locks == 0 &&
+        context->observers_pending == 0 &&
+        context->approvers_pending == 0 &&
+        !context->awaiting_approval)
     {
         /* no observers etc. left */
         mcd_dispatcher_run_handlers (context);
@@ -1185,7 +1192,7 @@ mcd_dispatcher_run_observers (McdDispatcherContext *context)
 }
 
 /*
- * mcd_dispatcher_context_approver_not_invoked:
+ * mcd_dispatcher_context_release_pending_approver:
  * @context: the #McdDispatcherContext.
  *
  * This function is called when an approver returned error on
@@ -1193,13 +1200,11 @@ mcd_dispatcher_run_observers (McdDispatcherContext *context)
  * have contacted. If all of them fail, then we continue the dispatching.
  */
 static void
-mcd_dispatcher_context_approver_not_invoked (McdDispatcherContext *context)
+mcd_dispatcher_context_release_pending_approver (McdDispatcherContext *context)
 {
-    g_return_if_fail (context->approvers_invoked > 0);
-    context->approvers_invoked--;
-
-    if (context->approvers_invoked == 0)
-        mcd_dispatcher_context_release_client_lock (context);
+    g_return_if_fail (context->approvers_pending > 0);
+    context->approvers_pending--;
+    mcd_dispatcher_context_check_client_locks (context);
 }
 
 static void
@@ -1214,12 +1219,6 @@ add_dispatch_operation_cb (TpClient *proxy, const GError *error,
                "%s",
                mcd_dispatch_operation_get_path (context->operation),
                context, tp_proxy_get_object_path (proxy), error->message);
-
-        /* if all approvers fail to add the DO, then we behave as if no
-         * approver was registered: i.e., we continue dispatching */
-        context->approvers_invoked--;
-        if (context->approvers_invoked == 0)
-            mcd_dispatcher_context_release_client_lock (context);
     }
     else
     {
@@ -1227,8 +1226,15 @@ add_dispatch_operation_cb (TpClient *proxy, const GError *error,
                tp_proxy_get_object_path (proxy),
                mcd_dispatch_operation_get_path (context->operation),
                context);
+        context->awaiting_approval = TRUE;
     }
 
+    /* If all approvers fail to add the DO, then we behave as if no
+     * approver was registered: i.e., we continue dispatching. If at least
+     * one approver accepted it, then we can still continue dispatching,
+     * since it will be stalled until awaiting_approval becomes FALSE. */
+    mcd_dispatcher_context_release_pending_approver (context);
+
     if (context->operation)
     {
         _mcd_dispatch_operation_unblock_finished (context->operation);
@@ -1255,9 +1261,8 @@ mcd_dispatcher_run_approvers (McdDispatcherContext *context)
     /* we temporarily increment this count and decrement it at the end of the
      * function, to make sure it won't become 0 while we are still invoking
      * approvers */
-    context->approvers_invoked = 1;
+    context->approvers_pending = 1;
 
-    context->client_locks++;
     channels = context->channels;
     g_hash_table_iter_init (&iter, priv->clients);
     while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &client))
@@ -1294,7 +1299,7 @@ mcd_dispatcher_run_approvers (McdDispatcherContext *context)
                "of context %p", client->name, dispatch_operation,
                context->operation, context);
 
-        context->approvers_invoked++;
+        context->approvers_pending++;
         _mcd_dispatch_operation_block_finished (context->operation);
 
         mcd_dispatcher_context_ref (context, "CTXREF06");
@@ -1310,7 +1315,7 @@ mcd_dispatcher_run_approvers (McdDispatcherContext *context)
 
     /* This matches the approvers count set to 1 at the beginning of the
      * function */
-    mcd_dispatcher_context_approver_not_invoked (context);
+    mcd_dispatcher_context_release_pending_approver (context);
 }
 
 static gboolean
@@ -1477,11 +1482,21 @@ on_operation_finished (McdDispatchOperation *operation,
             context->dispatcher, mcd_dispatch_operation_get_path (operation));
     }
 
+    /* Because of our calls to _mcd_dispatch_operation_block_finished,
+     * this cannot happen until all observers and all approvers have
+     * returned from ObserveChannels or AddDispatchOperation, respectively.
+     *
+     * (However, in observe_channels_cb we unblock finished a moment
+     * before we decrement observers_pending, so we can't actually assert
+     * that here.) */
+
+    g_assert (context->approvers_pending == 0);
+
     if (context->channels == NULL)
     {
         DEBUG ("Nothing left to dispatch");
 
-        if (context->client_locks > 0)
+        if (context->awaiting_approval)
         {
             /* this would have been released when all the locks were released,
              * but now we're never going to do that */
@@ -1507,14 +1522,15 @@ on_operation_finished (McdDispatchOperation *operation,
 
         /* this would have been released when all the locks were released, but
          * we're never going to do that */
-        g_assert (context->client_locks > 0);
+        g_assert (context->awaiting_approval);
         mcd_dispatcher_context_unref (context, "CTXREF13");
     }
     else
     {
         /* this is the lock set in mcd_dispatcher_run_approvers(): releasing
          * this will make the handlers run */
-        mcd_dispatcher_context_release_client_lock (context);
+        context->awaiting_approval = FALSE;
+        mcd_dispatcher_context_check_client_locks (context);
     }
 }
 
@@ -3633,7 +3649,7 @@ _mcd_dispatcher_add_channel_request (McdDispatcher *dispatcher,
 
             context = find_context_from_channel (dispatcher, channel);
             DEBUG ("channel %p is in context %p", channel, context);
-            if (context->approvers_invoked > 0)
+            if (context->approvers_pending > 0 || context->awaiting_approval)
             {
                 /* the existing channel is waiting for approval; but since the
                  * same channel has been requested, the approval operation must
-- 
1.5.6.5




More information about the telepathy-commits mailing list