#include "gdbusconnection.h"
#include "glibintl.h"
-#include "gioalias.h"
/**
* SECTION:gdbusnameowning
guint name_acquired_subscription_id;
guint name_lost_subscription_id;
- gboolean cancelled;
+ volatile gboolean cancelled; /* must hold lock when reading or modifying */
gboolean needs_release;
} Client;
g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
g_object_unref (client->connection);
}
- if (client->main_context != NULL)
- g_main_context_unref (client->main_context);
+ g_main_context_unref (client->main_context);
g_free (client->name);
if (client->user_data_free_func != NULL)
client->user_data_free_func (client->user_data);
static void
do_call (Client *client, CallType call_type)
{
+ GMainContext *current_context;
+
/* only schedule in idle if we're not in the right thread */
- if (g_main_context_get_thread_default () != client->main_context)
+ current_context = g_main_context_ref_thread_default ();
+ if (current_context != client->main_context)
schedule_call_in_idle (client, call_type);
else
actually_do_call (client, client->connection, call_type);
+ g_main_context_unref (current_context);
}
static void
call_acquired_handler (Client *client)
{
+ G_LOCK (lock);
if (client->previous_call != PREVIOUS_CALL_ACQUIRED)
{
client->previous_call = PREVIOUS_CALL_ACQUIRED;
if (!client->cancelled)
{
+ G_UNLOCK (lock);
do_call (client, CALL_TYPE_NAME_ACQUIRED);
+ goto out;
}
}
+ G_UNLOCK (lock);
+ out:
+ ;
}
static void
call_lost_handler (Client *client)
{
+ G_LOCK (lock);
if (client->previous_call != PREVIOUS_CALL_LOST)
{
client->previous_call = PREVIOUS_CALL_LOST;
if (!client->cancelled)
{
+ G_UNLOCK (lock);
do_call (client, CALL_TYPE_NAME_LOST);
+ goto out;
}
}
+ G_UNLOCK (lock);
+ out:
+ ;
}
/* ---------------------------------------------------------------------------------------------------- */
request_name_reply = 0;
result = NULL;
- result = g_dbus_connection_call_finish (client->connection,
+ /* don't use client->connection - it may be NULL already */
+ result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
res,
NULL);
if (result != NULL)
break;
}
+
if (subscribe)
{
+ GDBusConnection *connection = NULL;
+
+ /* if cancelled, there is no point in subscribing to signals - if not, make sure
+ * we use a known good Connection object since it may be set to NULL at any point
+ * after being cancelled
+ */
+ G_LOCK (lock);
+ if (!client->cancelled)
+ connection = g_object_ref (client->connection);
+ G_UNLOCK (lock);
+
/* start listening to NameLost and NameAcquired messages */
- client->name_lost_subscription_id =
- g_dbus_connection_signal_subscribe (client->connection,
- "org.freedesktop.DBus",
- "org.freedesktop.DBus",
- "NameLost",
- "/org/freedesktop/DBus",
- client->name,
- on_name_lost_or_acquired,
- client,
- NULL);
- client->name_acquired_subscription_id =
- g_dbus_connection_signal_subscribe (client->connection,
- "org.freedesktop.DBus",
- "org.freedesktop.DBus",
- "NameAcquired",
- "/org/freedesktop/DBus",
- client->name,
- on_name_lost_or_acquired,
- client,
- NULL);
+ if (connection != NULL)
+ {
+ client->name_lost_subscription_id =
+ g_dbus_connection_signal_subscribe (connection,
+ "org.freedesktop.DBus",
+ "org.freedesktop.DBus",
+ "NameLost",
+ "/org/freedesktop/DBus",
+ client->name,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ on_name_lost_or_acquired,
+ client,
+ NULL);
+ client->name_acquired_subscription_id =
+ g_dbus_connection_signal_subscribe (connection,
+ "org.freedesktop.DBus",
+ "org.freedesktop.DBus",
+ "NameAcquired",
+ "/org/freedesktop/DBus",
+ client->name,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ on_name_lost_or_acquired,
+ client,
+ NULL);
+ g_object_unref (connection);
+ }
}
client_unref (client);
g_variant_new ("(su)",
client->name,
client->flags),
+ G_VARIANT_TYPE ("(u)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
{
Client *client = user_data;
+ /* must not do anything if already cancelled */
+ G_LOCK (lock);
+ if (client->cancelled)
+ {
+ G_UNLOCK (lock);
+ goto out;
+ }
+ G_UNLOCK (lock);
+
client->connection = g_bus_get_finish (res, NULL);
if (client->connection == NULL)
{
/**
* g_bus_own_name_on_connection:
- * @connection: A #GDBusConnection that is not closed.
+ * @connection: A #GDBusConnection.
* @name: The well-known name to own.
* @flags: A set of flags from the #GBusNameOwnerFlags enumeration.
- * @name_acquired_handler: Handler to invoke when @name is acquired or %NULL.
- * @name_lost_handler: Handler to invoke when @name is lost or %NULL.
+ * @name_acquired_handler: (allow-none): Handler to invoke when @name is acquired or %NULL.
+ * @name_lost_handler: (allow-none): Handler to invoke when @name is lost or %NULL.
* @user_data: User data to pass to handlers.
- * @user_data_free_func: Function for freeing @user_data or %NULL.
+ * @user_data_free_func: (allow-none): Function for freeing @user_data or %NULL.
*
* Like g_bus_own_name() but takes a #GDBusConnection instead of a
* #GBusType.
Client *client;
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
- g_return_val_if_fail (!g_dbus_connection_is_closed (connection), 0);
g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), 0);
G_LOCK (lock);
client->name_lost_handler = name_lost_handler;
client->user_data = user_data;
client->user_data_free_func = user_data_free_func;
- client->main_context = g_main_context_get_thread_default ();
- if (client->main_context != NULL)
- g_main_context_ref (client->main_context);
+ client->main_context = g_main_context_ref_thread_default ();
client->connection = g_object_ref (connection);
* @bus_type: The type of bus to own a name on.
* @name: The well-known name to own.
* @flags: A set of flags from the #GBusNameOwnerFlags enumeration.
- * @bus_acquired_handler: Handler to invoke when connected to the bus of type @bus_type or %NULL.
- * @name_acquired_handler: Handler to invoke when @name is acquired or %NULL.
- * @name_lost_handler: Handler to invoke when @name is lost or %NULL.
+ * @bus_acquired_handler: (allow-none): Handler to invoke when connected to the bus of type @bus_type or %NULL.
+ * @name_acquired_handler: (allow-none): Handler to invoke when @name is acquired or %NULL.
+ * @name_lost_handler: (allow-none): Handler to invoke when @name is lost or %NULL.
* @user_data: User data to pass to handlers.
- * @user_data_free_func: Function for freeing @user_data or %NULL.
+ * @user_data_free_func: (allow-none): Function for freeing @user_data or %NULL.
*
* Starts acquiring @name on the bus specified by @bus_type and calls
* @name_acquired_handler and @name_lost_handler when the name is
client->name_lost_handler = name_lost_handler;
client->user_data = user_data;
client->user_data_free_func = user_data_free_func;
- client->main_context = g_main_context_get_thread_default ();
- if (client->main_context != NULL)
- g_main_context_ref (client->main_context);
+ client->main_context = g_main_context_ref_thread_default ();
if (map_id_to_client == NULL)
{
return client->id;
}
+typedef struct {
+ GClosure *bus_acquired_closure;
+ GClosure *name_acquired_closure;
+ GClosure *name_lost_closure;
+} OwnNameData;
+
+static OwnNameData *
+own_name_data_new (GClosure *bus_acquired_closure,
+ GClosure *name_acquired_closure,
+ GClosure *name_lost_closure)
+{
+ OwnNameData *data;
+
+ data = g_new0 (OwnNameData, 1);
+
+ if (bus_acquired_closure != NULL)
+ {
+ data->bus_acquired_closure = g_closure_ref (bus_acquired_closure);
+ g_closure_sink (bus_acquired_closure);
+ if (G_CLOSURE_NEEDS_MARSHAL (bus_acquired_closure))
+ g_closure_set_marshal (bus_acquired_closure, g_cclosure_marshal_generic);
+ }
+
+ if (name_acquired_closure != NULL)
+ {
+ data->name_acquired_closure = g_closure_ref (name_acquired_closure);
+ g_closure_sink (name_acquired_closure);
+ if (G_CLOSURE_NEEDS_MARSHAL (name_acquired_closure))
+ g_closure_set_marshal (name_acquired_closure, g_cclosure_marshal_generic);
+ }
+
+ if (name_lost_closure != NULL)
+ {
+ data->name_lost_closure = g_closure_ref (name_lost_closure);
+ g_closure_sink (name_lost_closure);
+ if (G_CLOSURE_NEEDS_MARSHAL (name_lost_closure))
+ g_closure_set_marshal (name_lost_closure, g_cclosure_marshal_generic);
+ }
+
+ return data;
+}
+
+static void
+own_with_closures_on_bus_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ OwnNameData *data = user_data;
+ GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
+
+ g_value_init (¶ms[0], G_TYPE_DBUS_CONNECTION);
+ g_value_set_object (¶ms[0], connection);
+
+ g_value_init (¶ms[1], G_TYPE_STRING);
+ g_value_set_string (¶ms[1], name);
+
+ g_closure_invoke (data->bus_acquired_closure, NULL, 2, params, NULL);
+
+ g_value_unset (params + 0);
+ g_value_unset (params + 1);
+}
+
+static void
+own_with_closures_on_name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ OwnNameData *data = user_data;
+ GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
+
+ g_value_init (¶ms[0], G_TYPE_DBUS_CONNECTION);
+ g_value_set_object (¶ms[0], connection);
+
+ g_value_init (¶ms[1], G_TYPE_STRING);
+ g_value_set_string (¶ms[1], name);
+
+ g_closure_invoke (data->name_acquired_closure, NULL, 2, params, NULL);
+
+ g_value_unset (params + 0);
+ g_value_unset (params + 1);
+}
+
+static void
+own_with_closures_on_name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ OwnNameData *data = user_data;
+ GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
+
+ g_value_init (¶ms[0], G_TYPE_DBUS_CONNECTION);
+ g_value_set_object (¶ms[0], connection);
+
+ g_value_init (¶ms[1], G_TYPE_STRING);
+ g_value_set_string (¶ms[1], name);
+
+ g_closure_invoke (data->name_lost_closure, NULL, 2, params, NULL);
+
+ g_value_unset (params + 0);
+ g_value_unset (params + 1);
+}
+
+static void
+bus_own_name_free_func (gpointer user_data)
+{
+ OwnNameData *data = user_data;
+
+ if (data->bus_acquired_closure != NULL)
+ g_closure_unref (data->bus_acquired_closure);
+
+ if (data->name_acquired_closure != NULL)
+ g_closure_unref (data->name_acquired_closure);
+
+ if (data->name_lost_closure != NULL)
+ g_closure_unref (data->name_lost_closure);
+
+ g_free (data);
+}
+
+/**
+ * g_bus_own_name_with_closures:
+ * @bus_type: The type of bus to own a name on.
+ * @name: The well-known name to own.
+ * @flags: A set of flags from the #GBusNameOwnerFlags enumeration.
+ * @bus_acquired_closure: (allow-none): #GClosure to invoke when connected to
+ * the bus of type @bus_type or %NULL.
+ * @name_acquired_closure: (allow-none): #GClosure to invoke when @name is
+ * acquired or %NULL.
+ * @name_lost_closure: (allow-none): #GClosure to invoke when @name is lost or
+ * %NULL.
+ *
+ * Version of g_bus_own_name() using closures instead of callbacks for
+ * easier binding in other languages.
+ *
+ * Returns: An identifier (never 0) that an be used with
+ * g_bus_unown_name() to stop owning the name.
+ *
+ * Rename to: g_bus_own_name
+ *
+ * Since: 2.26
+ */
+guint
+g_bus_own_name_with_closures (GBusType bus_type,
+ const gchar *name,
+ GBusNameOwnerFlags flags,
+ GClosure *bus_acquired_closure,
+ GClosure *name_acquired_closure,
+ GClosure *name_lost_closure)
+{
+ return g_bus_own_name (bus_type,
+ name,
+ flags,
+ bus_acquired_closure != NULL ? own_with_closures_on_bus_acquired : NULL,
+ name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
+ name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
+ own_name_data_new (bus_acquired_closure,
+ name_acquired_closure,
+ name_lost_closure),
+ bus_own_name_free_func);
+}
+
+/**
+ * g_bus_own_name_on_connection_with_closures:
+ * @connection: A #GDBusConnection.
+ * @name: The well-known name to own.
+ * @flags: A set of flags from the #GBusNameOwnerFlags enumeration.
+ * @name_acquired_closure: (allow-none): #GClosure to invoke when @name is
+ * acquired or %NULL.
+ * @name_lost_closure: (allow-none): #GClosure to invoke when @name is lost or
+ * %NULL.
+ *
+ * Version of g_bus_own_name_on_connection() using closures instead of callbacks for
+ * easier binding in other languages.
+ *
+ * Returns: An identifier (never 0) that an be used with
+ * g_bus_unown_name() to stop owning the name.
+ *
+ * Rename to: g_bus_own_name_on_connection
+ *
+ * Since: 2.26
+ */
+guint
+g_bus_own_name_on_connection_with_closures (GDBusConnection *connection,
+ const gchar *name,
+ GBusNameOwnerFlags flags,
+ GClosure *name_acquired_closure,
+ GClosure *name_lost_closure)
+{
+ return g_bus_own_name_on_connection (connection,
+ name,
+ flags,
+ name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
+ name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
+ own_name_data_new (NULL,
+ name_acquired_closure,
+ name_lost_closure),
+ bus_own_name_free_func);
+}
+
/**
* g_bus_unown_name:
* @owner_id: An identifier obtained from g_bus_own_name()
if (client != NULL)
{
/* Release the name if needed */
- if (client->needs_release && client->connection != NULL)
+ if (client->needs_release &&
+ client->connection != NULL &&
+ !g_dbus_connection_is_closed (client->connection))
{
GVariant *result;
GError *error;
"org.freedesktop.DBus", /* interface name */
"ReleaseName", /* method name */
g_variant_new ("(s)", client->name),
+ G_VARIANT_TYPE ("(u)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
client_unref (client);
}
}
-
-#define __G_DBUS_NAME_OWNING_C__
-#include "gioaliasdef.c"