GDBusInterface: add dup_object() method
authorDavid Zeuthen <davidz@redhat.com>
Thu, 26 Jan 2012 19:16:28 +0000 (14:16 -0500)
committerDavid Zeuthen <davidz@redhat.com>
Thu, 26 Jan 2012 19:20:08 +0000 (14:20 -0500)
This is needed for thread-safety ... yes, it would have been better to
make get_object() return a full reference and have something like a
peek_object() method return a borrowed reference for C convenience
(only a single vfunc would have been needed). But such an ABI break is
too late now...

Signed-off-by: David Zeuthen <davidz@redhat.com>
docs/reference/gio/gio-sections.txt
gio/gdbusinterface.c
gio/gdbusinterface.h
gio/gdbusinterfaceskeleton.c
gio/gdbusproxy.c
gio/gio.symbols

index 9d135e6..a671299 100644 (file)
@@ -3419,6 +3419,7 @@ GDBusInterface
 GDBusInterfaceIface
 g_dbus_interface_get_info
 g_dbus_interface_get_object
+g_dbus_interface_dup_object
 g_dbus_interface_set_object
 <SUBSECTION Standard>
 G_DBUS_INTERFACE
index 436ab3a..d1af07d 100644 (file)
@@ -66,11 +66,16 @@ g_dbus_interface_get_info (GDBusInterface *interface_)
 }
 
 /**
- * g_dbus_interface_get_object:
+ * g_dbus_interface_get_object: (skip)
  * @interface_: An exported D-Bus interface.
  *
  * Gets the #GDBusObject that @interface_ belongs to, if any.
  *
+ * <warning>It is not safe to use the returned object if @interface_
+ * or the returned object is being used from other threads. See
+ * g_dbus_interface_dup_object() for a thread-safe
+ * alternative.</warning>
+ *
  * Returns: (transfer none): A #GDBusObject or %NULL. The returned
  * reference belongs to @interface_ and should not be freed.
  *
@@ -84,6 +89,39 @@ g_dbus_interface_get_object (GDBusInterface *interface_)
 }
 
 /**
+ * g_dbus_interface_dup_object:
+ * @interface_: An exported D-Bus interface.
+ *
+ * Gets the #GDBusObject that @interface_ belongs to, if any.
+ *
+ * Returns: (transfer full): A #GDBusObject or %NULL. The returned
+ * reference should be freed with g_object_unref().
+ *
+ * Since: 2.32
+ *
+ * Rename to: g_dbus_interface_get_object
+ */
+GDBusObject *
+g_dbus_interface_dup_object (GDBusInterface *interface_)
+{
+  GDBusObject *ret;
+  g_return_val_if_fail (G_IS_DBUS_INTERFACE (interface_), NULL);
+  if (G_LIKELY (G_DBUS_INTERFACE_GET_IFACE (interface_)->dup_object != NULL))
+    {
+      ret = G_DBUS_INTERFACE_GET_IFACE (interface_)->dup_object (interface_);
+    }
+  else
+    {
+      g_warning ("No dup_object() vfunc on type %s - using get_object() in a way that is not thread-safe.",
+                 g_type_name_from_instance ((GTypeInstance *) interface_));
+      ret = G_DBUS_INTERFACE_GET_IFACE (interface_)->get_object (interface_);
+      if (ret != NULL)
+        g_object_ref (ret);
+    }
+  return ret;
+}
+
+/**
  * g_dbus_interface_set_object:
  * @interface_: An exported D-Bus interface.
  * @object: A #GDBusObject or %NULL.
index 967ca39..bce7587 100644 (file)
@@ -48,6 +48,7 @@ typedef struct _GDBusInterfaceIface GDBusInterfaceIface;
  * @get_info: Returns a #GDBusInterfaceInfo. See g_dbus_interface_get_info().
  * @get_object: Gets the enclosing #GDBusObject. See g_dbus_interface_get_object().
  * @set_object: Sets the enclosing #GDBusObject. See g_dbus_interface_set_object().
+ * @dup_object: Gets a reference to the enclosing #GDBusObject. See g_dbus_interface_dup_object(). Added in 2.32.
  *
  * Base type for D-Bus interfaces.
  *
@@ -62,6 +63,7 @@ struct _GDBusInterfaceIface
   GDBusObject          *(*get_object) (GDBusInterface      *interface_);
   void                  (*set_object) (GDBusInterface      *interface_,
                                        GDBusObject         *object);
+  GDBusObject          *(*dup_object) (GDBusInterface      *interface_);
 };
 
 GType                 g_dbus_interface_get_type         (void) G_GNUC_CONST;
@@ -69,6 +71,7 @@ GDBusInterfaceInfo   *g_dbus_interface_get_info         (GDBusInterface      *in
 GDBusObject          *g_dbus_interface_get_object       (GDBusInterface      *interface_);
 void                  g_dbus_interface_set_object       (GDBusInterface      *interface_,
                                                          GDBusObject         *object);
+GDBusObject          *g_dbus_interface_dup_object       (GDBusInterface      *interface_);
 
 G_END_DECLS
 
index e6c0a49..b3b5096 100644 (file)
@@ -415,6 +415,19 @@ g_dbus_interface_skeleton_get_object (GDBusInterface *interface_)
   return ret;
 }
 
+static GDBusObject *
+g_dbus_interface_skeleton_dup_object (GDBusInterface *interface_)
+{
+  GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (interface_);
+  GDBusObject *ret;
+  g_mutex_lock (&interface->priv->lock);
+  ret = interface->priv->object;
+  if (ret != NULL)
+    g_object_ref (ret);
+  g_mutex_unlock (&interface->priv->lock);
+  return ret;
+}
+
 static void
 g_dbus_interface_skeleton_set_object (GDBusInterface *interface_,
                                       GDBusObject    *object)
@@ -434,6 +447,7 @@ dbus_interface_interface_init (GDBusInterfaceIface *iface)
 {
   iface->get_info    = _g_dbus_interface_skeleton_get_info;
   iface->get_object  = g_dbus_interface_skeleton_get_object;
+  iface->dup_object  = g_dbus_interface_skeleton_dup_object;
   iface->set_object  = g_dbus_interface_skeleton_set_object;
 }
 
index 57ec011..52b222b 100644 (file)
@@ -153,6 +153,7 @@ struct _GDBusProxyPrivate
 
   gboolean initialized;
 
+  /* mutable, protected by properties_lock */
   GDBusObject *object;
 
   SignalSubscriptionData *signal_subscription_data;
@@ -3080,16 +3081,31 @@ _g_dbus_proxy_get_object (GDBusInterface *interface)
   return proxy->priv->object;
 }
 
+static GDBusObject *
+_g_dbus_proxy_dup_object (GDBusInterface *interface)
+{
+  GDBusProxy *proxy = G_DBUS_PROXY (interface);
+  GDBusObject *ret = NULL;
+
+  G_LOCK (properties_lock);
+  if (proxy->priv->object != NULL)
+    ret = g_object_ref (proxy->priv->object);
+  G_UNLOCK (properties_lock);
+  return ret;
+}
+
 static void
 _g_dbus_proxy_set_object (GDBusInterface *interface,
                           GDBusObject    *object)
 {
   GDBusProxy *proxy = G_DBUS_PROXY (interface);
+  G_LOCK (properties_lock);
   if (proxy->priv->object != NULL)
     g_object_remove_weak_pointer (G_OBJECT (proxy->priv->object), (gpointer *) &proxy->priv->object);
   proxy->priv->object = object;
   if (proxy->priv->object != NULL)
     g_object_add_weak_pointer (G_OBJECT (proxy->priv->object), (gpointer *) &proxy->priv->object);
+  G_UNLOCK (properties_lock);
 }
 
 static void
@@ -3097,6 +3113,7 @@ dbus_interface_iface_init (GDBusInterfaceIface *dbus_interface_iface)
 {
   dbus_interface_iface->get_info   = _g_dbus_proxy_get_info;
   dbus_interface_iface->get_object = _g_dbus_proxy_get_object;
+  dbus_interface_iface->dup_object = _g_dbus_proxy_dup_object;
   dbus_interface_iface->set_object = _g_dbus_proxy_set_object;
 }
 
index d363153..b614f16 100644 (file)
@@ -1569,6 +1569,7 @@ g_tls_password_get_flags
 g_tls_password_get_description
 g_dbus_interface_get_info
 g_dbus_interface_get_object
+g_dbus_interface_dup_object
 g_dbus_interface_get_type
 g_dbus_interface_set_object
 g_dbus_interface_skeleton_export