[glib] GDBusObjectManagerClient: Add locking



commit 4e7ef619ebe025bd97d2a3ef8dd8c1b7baa903b2
Author: David Zeuthen <davidz redhat com>
Date:   Mon Aug 29 16:20:50 2011 -0400

    GDBusObjectManagerClient: Add locking
    
    Signed-off-by: David Zeuthen <davidz redhat com>

 gio/gdbusobjectmanagerclient.c |  107 +++++++++++++++++++++++++++++++++-------
 1 files changed, 88 insertions(+), 19 deletions(-)
---
diff --git a/gio/gdbusobjectmanagerclient.c b/gio/gdbusobjectmanagerclient.c
index 9e8368d..2f581db 100644
--- a/gio/gdbusobjectmanagerclient.c
+++ b/gio/gdbusobjectmanagerclient.c
@@ -125,6 +125,8 @@
 
 struct _GDBusObjectManagerClientPrivate
 {
+  GMutex *lock;
+
   GBusType bus_type;
   GDBusConnection *connection;
   gchar *object_path;
@@ -212,15 +214,17 @@ g_dbus_object_manager_client_finalize (GObject *object)
   if (manager->priv->get_proxy_type_destroy_notify != NULL)
     manager->priv->get_proxy_type_destroy_notify (manager->priv->get_proxy_type_user_data);
 
+  g_mutex_free (manager->priv->lock);
+
   if (G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize != NULL)
     G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize (object);
 }
 
 static void
 g_dbus_object_manager_client_get_property (GObject    *_object,
-                                    guint       prop_id,
-                                    GValue     *value,
-                                    GParamSpec *pspec)
+                                           guint       prop_id,
+                                           GValue     *value,
+                                           GParamSpec *pspec)
 {
   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object);
 
@@ -254,9 +258,9 @@ g_dbus_object_manager_client_get_property (GObject    *_object,
 
 static void
 g_dbus_object_manager_client_set_property (GObject       *_object,
-                                    guint          prop_id,
-                                    const GValue  *value,
-                                    GParamSpec    *pspec)
+                                           guint          prop_id,
+                                           const GValue  *value,
+                                           GParamSpec    *pspec)
 {
   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object);
 
@@ -568,6 +572,7 @@ g_dbus_object_manager_client_init (GDBusObjectManagerClient *manager)
   manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
                                                G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
                                                GDBusObjectManagerClientPrivate);
+  manager->priv->lock = g_mutex_new ();
   manager->priv->map_object_path_to_object_proxy = g_hash_table_new_full (g_str_hash,
                                                                           g_str_equal,
                                                                           g_free,
@@ -707,7 +712,7 @@ g_dbus_object_manager_client_new (GDBusConnection               *connection,
  */
 GDBusObjectManager *
 g_dbus_object_manager_client_new_finish (GAsyncResult   *res,
-                                 GError        **error)
+                                         GError        **error)
 {
   GObject *object;
   GObject *source_object;
@@ -894,8 +899,12 @@ g_dbus_object_manager_client_new_for_bus_finish (GAsyncResult   *res,
 GDBusConnection *
 g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager)
 {
+  GDBusConnection *ret;
   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
-  return manager->priv->connection;
+  g_mutex_lock (manager->priv->lock);
+  ret = manager->priv->connection;
+  g_mutex_unlock (manager->priv->lock);
+  return ret;
 }
 
 /**
@@ -912,8 +921,12 @@ g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager)
 const gchar *
 g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager)
 {
+  const gchar *ret;
   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
-  return manager->priv->name;
+  g_mutex_lock (manager->priv->lock);
+  ret = manager->priv->name;
+  g_mutex_unlock (manager->priv->lock);
+  return ret;
 }
 
 /**
@@ -930,8 +943,12 @@ g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager)
 GDBusObjectManagerClientFlags
 g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager)
 {
+  GDBusObjectManagerClientFlags ret;
   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE);
-  return manager->priv->flags;
+  g_mutex_lock (manager->priv->lock);
+  ret = manager->priv->flags;
+  g_mutex_unlock (manager->priv->lock);
+  return ret;
 }
 
 /**
@@ -951,8 +968,12 @@ g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager)
 gchar *
 g_dbus_object_manager_client_get_name_owner (GDBusObjectManagerClient *manager)
 {
+  gchar *ret;
   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
-  return g_strdup (manager->priv->name_owner);
+  g_mutex_lock (manager->priv->lock);
+  ret = g_strdup (manager->priv->name_owner);
+  g_mutex_unlock (manager->priv->lock);
+  return ret;
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -973,9 +994,15 @@ signal_cb (GDBusConnection *connection,
   GDBusObjectProxy *object_proxy;
   GDBusInterface *interface;
 
+  g_mutex_lock (manager->priv->lock);
   object_proxy = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
   if (object_proxy == NULL)
-    goto out;
+    {
+      g_mutex_unlock (manager->priv->lock);
+      goto out;
+    }
+  g_object_ref (object_proxy);
+  g_mutex_unlock (manager->priv->lock);
 
   //g_debug ("yay, signal_cb %s %s: %s\n", signal_name, object_path, g_variant_print (parameters, TRUE));
 
@@ -1062,7 +1089,8 @@ signal_cb (GDBusConnection *connection,
     }
 
  out:
-  ;
+  if (object_proxy != NULL)
+    g_object_ref (object_proxy);
 }
 
 static void
@@ -1196,6 +1224,7 @@ on_notify_g_name_owner (GObject    *object,
   gchar *old_name_owner;
   gchar *new_name_owner;
 
+  g_mutex_lock (manager->priv->lock);
   old_name_owner = manager->priv->name_owner;
   new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
   manager->priv->name_owner = NULL;
@@ -1205,16 +1234,19 @@ on_notify_g_name_owner (GObject    *object,
       GList *l;
       GList *proxies;
 
+      /* remote manager changed; nuke all local proxies  */
+      proxies = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
+      g_list_foreach (proxies, (GFunc) g_object_ref, NULL);
+      g_hash_table_remove_all (manager->priv->map_object_path_to_object_proxy);
+
+      g_mutex_unlock (manager->priv->lock);
+
       /* do the :name-owner notify with a NULL name - this way the user knows
        * the ::object-proxy-removed following is because the name owner went
        * away
        */
       g_object_notify (G_OBJECT (manager), "name-owner");
 
-      /* remote manager changed; nuke all local proxies  */
-      proxies = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
-      g_list_foreach (proxies, (GFunc) g_object_ref, NULL);
-      g_hash_table_remove_all (manager->priv->map_object_path_to_object_proxy);
       for (l = proxies; l != NULL; l = l->next)
         {
           GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data);
@@ -1226,6 +1258,10 @@ on_notify_g_name_owner (GObject    *object,
       /* nuke local filter */
       maybe_unsubscribe_signals (manager);
     }
+  else
+    {
+      g_mutex_unlock (manager->priv->lock);
+    }
 
   if (new_name_owner != NULL)
     {
@@ -1263,7 +1299,9 @@ on_notify_g_name_owner (GObject    *object,
       /* do the :name-owner notify *AFTER* emitting ::object-proxy-added signals - this
        * way the user knows that the signals were emitted because the name owner came back
        */
+      g_mutex_lock (manager->priv->lock);
       manager->priv->name_owner = new_name_owner;
+      g_mutex_unlock (manager->priv->lock);
       g_object_notify (G_OBJECT (manager), "name-owner");
 
     }
@@ -1379,10 +1417,16 @@ add_interfaces (GDBusObjectManagerClient *manager,
   GVariantIter iter;
   const gchar *interface_name;
   GVariant *properties;
+  GList *interface_added_signals, *l;
+  GDBusProxy *interface_proxy;
 
   g_return_if_fail (g_dbus_is_unique_name (name_owner));
 
+  g_mutex_lock (manager->priv->lock);
+
+  interface_added_signals = NULL;
   added = FALSE;
+
   op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
   if (op == NULL)
     {
@@ -1405,6 +1449,7 @@ add_interfaces (GDBusObjectManagerClient *manager,
                          NULL);
       added = TRUE;
     }
+  g_object_ref (op);
 
   g_variant_iter_init (&iter, ifaces_and_properties);
   while (g_variant_iter_next (&iter,
@@ -1412,7 +1457,6 @@ add_interfaces (GDBusObjectManagerClient *manager,
                               &interface_name,
                               &properties))
     {
-      GDBusProxy *interface_proxy;
       GError *error;
       GType interface_proxy_type;
 
@@ -1476,12 +1520,23 @@ add_interfaces (GDBusObjectManagerClient *manager,
 
           _g_dbus_object_proxy_add_interface (op, interface_proxy);
           if (!added)
-            g_signal_emit_by_name (manager, "interface-added", op, interface_proxy);
+            interface_added_signals = g_list_append (interface_added_signals, g_object_ref (interface_proxy));
           g_object_unref (interface_proxy);
         }
       g_variant_unref (properties);
     }
 
+  g_mutex_unlock (manager->priv->lock);
+
+  /* now that we don't hold the lock any more, emit signals */
+  for (l = interface_added_signals; l != NULL; l = l->next)
+    {
+      interface_proxy = G_DBUS_PROXY (l->data);
+      g_signal_emit_by_name (manager, "interface-added", op, interface_proxy);
+      g_object_unref (interface_proxy);
+    }
+  g_list_free (interface_added_signals);
+
   if (added)
     {
       g_hash_table_insert (manager->priv->map_object_path_to_object_proxy,
@@ -1489,6 +1544,8 @@ add_interfaces (GDBusObjectManagerClient *manager,
                            op);
       g_signal_emit_by_name (manager, "object-added", op);
     }
+  g_object_unref (op);
+
 }
 
 static void
@@ -1502,12 +1559,15 @@ remove_interfaces (GDBusObjectManagerClient   *manager,
   guint num_interfaces;
   guint num_interfaces_to_remove;
 
+  g_mutex_lock (manager->priv->lock);
+
   op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
   if (op == NULL)
     {
       g_warning ("%s: Processing InterfaceRemoved signal for path %s but no object proxy exists",
                  G_STRLOC,
                  object_path);
+      g_mutex_unlock (manager->priv->lock);
       goto out;
     }
 
@@ -1523,11 +1583,14 @@ remove_interfaces (GDBusObjectManagerClient   *manager,
     {
       g_object_ref (op);
       g_warn_if_fail (g_hash_table_remove (manager->priv->map_object_path_to_object_proxy, object_path));
+      g_mutex_unlock (manager->priv->lock);
       g_signal_emit_by_name (manager, "object-removed", op);
       g_object_unref (op);
     }
   else
     {
+      g_object_ref (op);
+      g_mutex_unlock (manager->priv->lock);
       for (n = 0; interface_names != NULL && interface_names[n] != NULL; n++)
         {
           GDBusInterface *interface;
@@ -1539,6 +1602,7 @@ remove_interfaces (GDBusObjectManagerClient   *manager,
               g_object_unref (interface);
             }
         }
+      g_object_unref (op);
     }
  out:
   ;
@@ -1619,9 +1683,11 @@ g_dbus_object_manager_client_get_object (GDBusObjectManager *_manager,
   GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
   GDBusObject *ret;
 
+  g_mutex_lock (manager->priv->lock);
   ret = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
   if (ret != NULL)
     g_object_ref (ret);
+  g_mutex_unlock (manager->priv->lock);
   return ret;
 }
 
@@ -1654,8 +1720,11 @@ g_dbus_object_manager_client_get_objects (GDBusObjectManager *_manager)
 
   g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
 
+  g_mutex_lock (manager->priv->lock);
   ret = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
   g_list_foreach (ret, (GFunc) g_object_ref, NULL);
+  g_mutex_unlock (manager->priv->lock);
+
   return ret;
 }
 



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