[Telepathy-commits] [telepathy-glib/master] TpBaseConnection: improve ordering of events for channel managers

Simon McVittie simon.mcvittie at collabora.co.uk
Thu Oct 30 09:31:59 PDT 2008


Same rationale as for channel factories (previous commit).
---
 telepathy-glib/base-connection.c |   78 ++++++++++++++++++++++++++------------
 1 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/telepathy-glib/base-connection.c b/telepathy-glib/base-connection.c
index 88ad9a3..866de64 100644
--- a/telepathy-glib/base-connection.c
+++ b/telepathy-glib/base-connection.c
@@ -943,6 +943,13 @@ factory_channel_error_cb (TpChannelFactoryIface *factory,
 
 /* Channel manager signal handlers */
 
+typedef struct {
+    TpBaseConnection *self;
+    /* borrowed TpExportableChannel => itself if suppress_handler,
+     * omitted otherwise */
+    GHashTable *suppress_handler;
+} ManagerNewChannelContext;
+
 static void
 manager_new_channel (gpointer key,
                      gpointer value,
@@ -950,17 +957,18 @@ manager_new_channel (gpointer key,
 {
   TpExportableChannel *channel = TP_EXPORTABLE_CHANNEL (key);
   GSList *request_tokens = value;
-  TpBaseConnection *self = TP_BASE_CONNECTION (data);
-  gchar *object_path, *channel_type;
-  guint handle_type, handle;
+  ManagerNewChannelContext *context = data;
+  TpBaseConnection *self = TP_BASE_CONNECTION (context->self);
+  gchar *object_path;
   GSList *iter;
   gboolean suppress_handler = FALSE;
   gboolean satisfies_create_channel = FALSE;
   gboolean satisfies_request_channel = FALSE;
   ChannelRequest *first_ensure = NULL;
 
-  exportable_channel_get_old_info (channel, &object_path, &channel_type,
-      &handle_type, &handle);
+  g_object_get (channel,
+      "object-path", &object_path,
+      NULL);
 
   /* suppress_handler on Connection.NewChannel should be TRUE if:
    *   - any satisfied requests were calls to CreateChannel; or
@@ -1006,13 +1014,11 @@ manager_new_channel (gpointer key,
     }
 break_loop_early:
 
+  /* put the channel in the suppress_handler hash table if it needs
+   * suppress_handler set when signalling NewChannel */
   if (request_tokens != NULL &&
       (satisfies_create_channel || !satisfies_request_channel))
-    suppress_handler = TRUE;
-
-  tp_svc_connection_emit_new_channel (self, object_path, channel_type,
-      handle_type, handle, suppress_handler);
-
+    g_hash_table_insert (context->suppress_handler, channel, channel);
 
   /* If the only type of request satisfied by this new channel is
    * EnsureChannel, give exactly one request Yours=True.
@@ -1033,18 +1039,6 @@ break_loop_early:
     }
 
   g_free (object_path);
-  g_free (channel_type);
-}
-
-
-static void
-manager_new_channels_foreach (gpointer key,
-                              gpointer value,
-                              gpointer data)
-{
-  GPtrArray *details = data;
-
-  g_ptr_array_add (details, get_channel_details (G_OBJECT (key)));
 }
 
 
@@ -1054,18 +1048,54 @@ manager_new_channels_cb (TpChannelManager *manager,
                          TpBaseConnection *self)
 {
   GPtrArray *array;
+  ManagerNewChannelContext context = { self, g_hash_table_new (NULL, NULL) };
+  GHashTableIter iter;
+  gpointer key, value;
 
   g_assert (TP_IS_CHANNEL_MANAGER (manager));
   g_assert (TP_IS_BASE_CONNECTION (self));
 
+  /* satisfy the RequestChannel/CreateChannel/EnsureChannel calls; as
+   * a side-effect, fill in context.suppress_handler with those channels
+   * that will have to be signalled with suppress_handler = TRUE */
+  g_hash_table_foreach (channels, manager_new_channel, &context);
+
+  /* Emit NewChannels */
   array = g_ptr_array_sized_new (g_hash_table_size (channels));
-  g_hash_table_foreach (channels, manager_new_channels_foreach, array);
+  g_hash_table_iter_init (&iter, channels);
+
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      g_ptr_array_add (array, get_channel_details (G_OBJECT (key)));
+    }
+
   tp_svc_connection_interface_requests_emit_new_channels (self,
       array);
+
   g_ptr_array_foreach (array, (GFunc) g_value_array_free, NULL);
   g_ptr_array_free (array, TRUE);
 
-  g_hash_table_foreach (channels, manager_new_channel, self);
+  /* Emit NewChannel */
+  g_hash_table_iter_init (&iter, channels);
+
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      gboolean suppress_handler = (
+          g_hash_table_lookup (context.suppress_handler, key) != NULL);
+      gchar *object_path, *channel_type;
+      guint handle_type, handle;
+
+      exportable_channel_get_old_info (TP_EXPORTABLE_CHANNEL (key),
+          &object_path, &channel_type, &handle_type, &handle);
+
+      tp_svc_connection_emit_new_channel (self, object_path, channel_type,
+          handle_type, handle, suppress_handler);
+
+      g_free (object_path);
+      g_free (channel_type);
+    }
+
+  g_hash_table_destroy (context.suppress_handler);
 }
 
 
-- 
1.5.6.5




More information about the Telepathy-commits mailing list