[Telepathy-commits] [telepathy-glib/master] fd.o#18291: when listing connection managers, wait for them all to be ready

Simon McVittie simon.mcvittie at collabora.co.uk
Fri Feb 13 03:10:57 PST 2009


---
 telepathy-glib/connection-manager.c |   77 +++++++++++++++++++++++++++--------
 1 files changed, 60 insertions(+), 17 deletions(-)

diff --git a/telepathy-glib/connection-manager.c b/telepathy-glib/connection-manager.c
index f076700..373102c 100644
--- a/telepathy-glib/connection-manager.c
+++ b/telepathy-glib/connection-manager.c
@@ -1612,29 +1612,73 @@ steal_into_ptr_array (gpointer key,
 typedef struct
 {
   GHashTable *table;
+  GPtrArray *arr;
   TpConnectionManagerListCb callback;
   gpointer user_data;
   GDestroyNotify destroy;
   TpProxyPendingCall *pending_call;
   size_t base_len;
+  gsize refcount;
+  gsize cms_to_ready;
   unsigned getting_names:1;
-  guint refcount:2;
 } _ListContext;
 
 static void
 list_context_unref (_ListContext *list_context)
 {
+  guint i;
+
   if (--list_context->refcount > 0)
     return;
 
   if (list_context->destroy != NULL)
     list_context->destroy (list_context->user_data);
 
+  if (list_context->arr != NULL)
+    {
+      for (i = 0; i < list_context->arr->len; i++)
+        {
+          TpConnectionManager *cm = g_ptr_array_index (list_context->arr, i);
+
+          if (cm != NULL)
+            g_object_unref (cm);
+        }
+
+      g_ptr_array_free (list_context->arr, TRUE);
+    }
+
   g_hash_table_destroy (list_context->table);
   g_slice_free (_ListContext, list_context);
 }
 
 static void
+tp_list_connection_managers_cm_ready (TpConnectionManager *cm,
+                                      const GError *error,
+                                      gpointer user_data,
+                                      GObject *weak_object)
+{
+  _ListContext *list_context = user_data;
+
+  /* ignore errors here - all we guarantee is that the CM is ready
+   * *if possible* */
+
+  if ((--list_context->cms_to_ready) == 0)
+    {
+      TpConnectionManager **cms;
+      guint n_cms = list_context->arr->len;
+
+      g_assert (list_context->callback != NULL);
+
+      g_ptr_array_add (list_context->arr, NULL);
+      cms = (TpConnectionManager **) list_context->arr->pdata;
+
+      list_context->callback (cms, n_cms, NULL, list_context->user_data,
+          weak_object);
+      list_context->callback = NULL;
+    }
+}
+
+static void
 tp_list_connection_managers_got_names (TpDBusDaemon *bus_daemon,
                                        const gchar **names,
                                        const GError *error,
@@ -1673,29 +1717,26 @@ tp_list_connection_managers_got_names (TpDBusDaemon *bus_daemon,
 
   if (list_context->getting_names)
     {
-      /* actually call the callback */
-      GPtrArray *arr = g_ptr_array_sized_new (g_hash_table_size
+      /* now that we have all the CMs, wait for them all to be ready */
+      guint i;
+
+      list_context->arr = g_ptr_array_sized_new (g_hash_table_size
               (list_context->table));
-      TpConnectionManager **cms;
-      TpConnectionManager * const *cm_iter;
-      gsize n_cms;
 
       g_hash_table_foreach_steal (list_context->table, steal_into_ptr_array,
-          arr);
-      n_cms = arr->len;
-      g_ptr_array_add (arr, NULL);
+          list_context->arr);
 
-      cms = (TpConnectionManager **) g_ptr_array_free (arr, FALSE);
-      list_context->callback (cms, n_cms, NULL, list_context->user_data,
-          weak_object);
-      list_context->callback = NULL;
+      list_context->cms_to_ready = list_context->arr->len;
+      list_context->refcount += list_context->cms_to_ready;
 
-      for (cm_iter = cms; *cm_iter != NULL; cm_iter++)
+      for (i = 0; i < list_context->cms_to_ready; i++)
         {
-          g_object_unref (*cm_iter);
-        }
+          TpConnectionManager *cm = g_ptr_array_index (list_context->arr, i);
 
-      g_free (cms);
+          tp_connection_manager_call_when_ready (cm,
+              tp_list_connection_managers_cm_ready, list_context,
+              (GDestroyNotify) list_context_unref, weak_object);
+        }
     }
   else
     {
@@ -1741,6 +1782,8 @@ tp_list_connection_managers (TpDBusDaemon *bus_daemon,
   list_context->refcount = 1;
   list_context->table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
       g_object_unref);
+  list_context->arr = NULL;
+  list_context->cms_to_ready = 0;
 
   tp_cli_dbus_daemon_call_list_activatable_names (bus_daemon, 2000,
       tp_list_connection_managers_got_names, list_context,
-- 
1.5.6.5




More information about the telepathy-commits mailing list