* <example id="gdbus-wellknown-proxy"><title>GDBusProxy for a well-known-name</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-watch-proxy.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
*/
+/* ---------------------------------------------------------------------------------------------------- */
+
+G_LOCK_DEFINE_STATIC (signal_subscription_lock);
+
+typedef struct
+{
+ volatile gint ref_count;
+ GDBusProxy *proxy;
+} SignalSubscriptionData;
+
+static SignalSubscriptionData *
+signal_subscription_ref (SignalSubscriptionData *data)
+{
+ g_atomic_int_inc (&data->ref_count);
+ return data;
+}
+
+static void
+signal_subscription_unref (SignalSubscriptionData *data)
+{
+ if (g_atomic_int_dec_and_test (&data->ref_count))
+ {
+ g_slice_free (SignalSubscriptionData, data);
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
struct _GDBusProxyPrivate
{
GBusType bus_type;
GDBusInterfaceInfo *expected_interface;
- guint properties_changed_subscriber_id;
- guint signals_subscriber_id;
+ guint properties_changed_subscription_id;
+ guint signals_subscription_id;
gboolean initialized;
GDBusObject *object;
+
+ SignalSubscriptionData *signal_subscription_data;
};
enum
);
static void
+g_dbus_proxy_dispose (GObject *object)
+{
+ GDBusProxy *proxy = G_DBUS_PROXY (object);
+ G_LOCK (signal_subscription_lock);
+ if (proxy->priv->signal_subscription_data != NULL)
+ {
+ proxy->priv->signal_subscription_data->proxy = NULL;
+ signal_subscription_unref (proxy->priv->signal_subscription_data);
+ proxy->priv->signal_subscription_data = NULL;
+ }
+ G_UNLOCK (signal_subscription_lock);
+
+ G_OBJECT_CLASS (g_dbus_proxy_parent_class)->dispose (object);
+}
+
+static void
g_dbus_proxy_finalize (GObject *object)
{
GDBusProxy *proxy = G_DBUS_PROXY (object);
g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
proxy->priv->name_owner_changed_subscription_id);
- if (proxy->priv->properties_changed_subscriber_id > 0)
+ if (proxy->priv->properties_changed_subscription_id > 0)
g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
- proxy->priv->properties_changed_subscriber_id);
+ proxy->priv->properties_changed_subscription_id);
- if (proxy->priv->signals_subscriber_id > 0)
+ if (proxy->priv->signals_subscription_id > 0)
g_dbus_connection_signal_unsubscribe (proxy->priv->connection,
- proxy->priv->signals_subscriber_id);
+ proxy->priv->signals_subscription_id);
if (proxy->priv->connection != NULL)
g_object_unref (proxy->priv->connection);
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->dispose = g_dbus_proxy_dispose;
gobject_class->finalize = g_dbus_proxy_finalize;
gobject_class->set_property = g_dbus_proxy_set_property;
gobject_class->get_property = g_dbus_proxy_get_property;
g_dbus_proxy_init (GDBusProxy *proxy)
{
proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, G_TYPE_DBUS_PROXY, GDBusProxyPrivate);
+ proxy->priv->signal_subscription_data = g_slice_new0 (SignalSubscriptionData);
+ proxy->priv->signal_subscription_data->ref_count = 1;
+ proxy->priv->signal_subscription_data->proxy = proxy;
proxy->priv->properties = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
GVariant *parameters,
gpointer user_data)
{
- GDBusProxy *proxy = G_DBUS_PROXY (user_data);
+ SignalSubscriptionData *data = user_data;
+ GDBusProxy *proxy;
+
+ G_LOCK (signal_subscription_lock);
+ proxy = data->proxy;
+ if (proxy == NULL)
+ goto out;
+ g_object_ref (proxy);
+ G_UNLOCK (signal_subscription_lock);
if (!proxy->priv->initialized)
goto out;
signal_name,
parameters);
out:
- ;
+ if (proxy != NULL)
+ g_object_unref (proxy);
}
/* ---------------------------------------------------------------------------------------------------- */
GVariant *parameters,
gpointer user_data)
{
- GDBusProxy *proxy = G_DBUS_PROXY (user_data);
+ SignalSubscriptionData *data = user_data;
+ GDBusProxy *proxy;
const gchar *interface_name_for_signal;
GVariant *changed_properties;
gchar **invalidated_properties;
GVariant *value;
guint n;
+ G_LOCK (signal_subscription_lock);
+ proxy = data->proxy;
+ if (proxy == NULL)
+ goto out;
+ g_object_ref (proxy);
+ G_UNLOCK (signal_subscription_lock);
+
changed_properties = NULL;
invalidated_properties = NULL;
if (changed_properties != NULL)
g_variant_unref (changed_properties);
g_free (invalidated_properties);
+ if (proxy != NULL)
+ g_object_unref (proxy);
}
/* ---------------------------------------------------------------------------------------------------- */
GVariant *parameters,
gpointer user_data)
{
- GDBusProxy *proxy = G_DBUS_PROXY (user_data);
+ SignalSubscriptionData *data = user_data;
+ GDBusProxy *proxy;
const gchar *old_owner;
const gchar *new_owner;
+ G_LOCK (signal_subscription_lock);
+ proxy = data->proxy;
+ if (proxy == NULL)
+ goto out;
+ g_object_ref (proxy);
+ G_UNLOCK (signal_subscription_lock);
+
/* if we are already trying to load properties, cancel that */
if (proxy->priv->get_all_cancellable != NULL)
{
}
out:
- ;
+ if (proxy != NULL)
+ g_object_unref (proxy);
}
/* ---------------------------------------------------------------------------------------------------- */
if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES))
{
/* subscribe to PropertiesChanged() */
- proxy->priv->properties_changed_subscriber_id =
+ proxy->priv->properties_changed_subscription_id =
g_dbus_connection_signal_subscribe (proxy->priv->connection,
proxy->priv->name,
"org.freedesktop.DBus.Properties",
proxy->priv->interface_name,
G_DBUS_SIGNAL_FLAGS_NONE,
on_properties_changed,
- proxy,
- NULL);
+ signal_subscription_ref (proxy->priv->signal_subscription_data),
+ (GDestroyNotify) signal_subscription_unref);
}
if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS))
{
/* subscribe to all signals for the object */
- proxy->priv->signals_subscriber_id =
+ proxy->priv->signals_subscription_id =
g_dbus_connection_signal_subscribe (proxy->priv->connection,
proxy->priv->name,
proxy->priv->interface_name,
NULL, /* arg0 */
G_DBUS_SIGNAL_FLAGS_NONE,
on_signal_received,
- proxy,
- NULL);
+ signal_subscription_ref (proxy->priv->signal_subscription_data),
+ (GDestroyNotify) signal_subscription_unref);
}
if (proxy->priv->name != NULL && !g_dbus_is_unique_name (proxy->priv->name))
proxy->priv->name, /* arg0 */
G_DBUS_SIGNAL_FLAGS_NONE,
on_name_owner_changed,
- proxy,
- NULL);
+ signal_subscription_ref (proxy->priv->signal_subscription_data),
+ (GDestroyNotify) signal_subscription_unref);
}
}