[glib] action exporter: clarify threading situation



commit 14900d37f46ecab99deb4fd97822f1f2ec105c40
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Dec 7 20:39:23 2011 -0500

    action exporter: clarify threading situation
    
    Exporting can only be done relative to a particular given main context
    and all interaction with the action group must be on that same context.
    
    Fix up the implementation so that the user can specify that context with
    the normal (thread default) mechanism and document the limitation on the
    API.
    
    Adjust the testcase to adhere to the documentation limitations.  It
    passes now.

 gio/gactiongroupexporter.c |   16 ++++++++++++++--
 gio/tests/actions.c        |   41 ++++++++++++++++++-----------------------
 2 files changed, 32 insertions(+), 25 deletions(-)
---
diff --git a/gio/gactiongroupexporter.c b/gio/gactiongroupexporter.c
index 136928c..ef8f18a 100644
--- a/gio/gactiongroupexporter.c
+++ b/gio/gactiongroupexporter.c
@@ -216,6 +216,7 @@ typedef struct
 {
   GActionGroup    *action_group;
   GDBusConnection *connection;
+  GMainContext    *context;
   gchar           *object_path;
   GHashTable      *pending_changes;
   GSource         *pending_source;
@@ -329,7 +330,7 @@ g_action_group_exporter_set_events (GActionGroupExporter *exporter,
       source = g_idle_source_new ();
       exporter->pending_source = source;
       g_source_set_callback (source, g_action_group_exporter_dispatch_events, exporter, NULL);
-      g_source_attach (source, NULL);
+      g_source_attach (source, exporter->context);
       g_source_unref (source);
     }
 
@@ -566,6 +567,7 @@ g_action_group_exporter_free (gpointer user_data)
   if (exporter->pending_source)
     g_source_destroy (exporter->pending_source);
 
+  g_main_context_unref (exporter->context);
   g_object_unref (exporter->connection);
   g_object_unref (exporter->action_group);
   g_free (exporter->object_path);
@@ -585,7 +587,7 @@ g_action_group_exporter_free (gpointer user_data)
  * The implemented D-Bus API should be considered private.  It is
  * subject to change in the future.
  *
- * A given * object path can only have one action group exported on it.
+ * A given object path can only have one action group exported on it.
  * If this constraint is violated, the export will fail and 0 will be
  * returned (with @error set accordingly).
  *
@@ -593,6 +595,15 @@ g_action_group_exporter_free (gpointer user_data)
  * g_dbus_connection_unexport_action_group() with the return value of
  * this function.
  *
+ * The thread default main context is taken at the time of this call.
+ * All incoming action activations and state change requests are
+ * reported from this context.  Any changes on the action group that
+ * cause it to emit signals must also come from this same context.
+ * Since incoming action activations and state change requests are
+ * rather likely to cause changes on the action group, this effectively
+ * limits a given action group to being exported from only one main
+ * context.
+ *
  * Returns: the ID of the export (never zero), or 0 in case of failure
  *
  * Since: 2.32
@@ -633,6 +644,7 @@ g_dbus_connection_export_action_group (GDBusConnection  *connection,
       return 0;
     }
 
+  exporter->context = g_main_context_ref_thread_default ();
   exporter->pending_changes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
   exporter->pending_source = NULL;
   exporter->action_group = g_object_ref (action_group);
diff --git a/gio/tests/actions.c b/gio/tests/actions.c
index c924438..63ffe48 100644
--- a/gio/tests/actions.c
+++ b/gio/tests/actions.c
@@ -625,32 +625,21 @@ test_dbus_export (void)
 }
 
 static gpointer
-do_activate (gpointer data)
-{
-  GSimpleActionGroup *group = data;
-  gint i;
-  GAction *action;
-
-  for (i = 0; i < 1000000; i++)
-    {
-      action = g_simple_action_group_lookup (group, "a");
-      g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
-                                   !g_action_get_enabled (action));
-    }
-
-  return NULL;
-}
-
-static gpointer
 do_export (gpointer data)
 {
   GActionGroup *group = data;
+  GMainContext *ctx;
   gint i;
   GError *error = NULL;
   guint id;
   GDBusConnection *bus;
+  GAction *action;
   gchar *path;
 
+  ctx = g_main_context_new ();
+
+  g_main_context_push_thread_default (ctx);
+
   bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
   path = g_strdup_printf("/%p", data);
 
@@ -658,12 +647,23 @@ do_export (gpointer data)
     {
       id = g_dbus_connection_export_action_group (bus, path, G_ACTION_GROUP (group), &error);
       g_assert_no_error (error);
+
+      action = g_simple_action_group_lookup (G_SIMPLE_ACTION_GROUP (group), "a");
+      g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
+                                   !g_action_get_enabled (action));
+
       g_dbus_connection_unexport_action_group (bus, id);
+
+      while (g_main_context_iteration (ctx, FALSE));
     }
 
   g_free (path);
   g_object_unref (bus);
 
+  g_main_context_pop_thread_default (ctx);
+
+  g_main_context_unref (ctx);
+
   return NULL;
 }
 
@@ -671,7 +671,6 @@ static void
 test_dbus_threaded (void)
 {
   GSimpleActionGroup *group[10];
-  GThread *call[10];
   GThread *export[10];
   static GActionEntry entries[] = {
     { "a",  activate_action, NULL, NULL, NULL },
@@ -683,15 +682,11 @@ test_dbus_threaded (void)
     {
       group[i] = g_simple_action_group_new ();
       g_simple_action_group_add_entries (group[i], entries, G_N_ELEMENTS (entries), NULL);
-      call[i] = g_thread_new ("call", do_activate, group[i]);
       export[i] = g_thread_new ("export", do_export, group[i]);
     }
 
   for (i = 0; i < 10; i++)
-    {
-      g_thread_join (call[i]);
-      g_thread_join (export[i]);
-    }
+    g_thread_join (export[i]);
 
   for (i = 0; i < 10; i++)
     g_object_unref (group[i]);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]