GDBusMenuModel: become thread-aware

Allow imports of the same menu on multiple different main contexts at
the same time by creating a separate object for each context.
This commit is contained in:
Ryan Lortie
2011-12-07 21:22:51 -05:00
parent 25ffde957c
commit 13e084437b

View File

@@ -47,7 +47,8 @@
* particular thing: * particular thing:
* *
* - GDBusMenuPath represents a D-Bus object path on a particular * - GDBusMenuPath represents a D-Bus object path on a particular
* unique bus name on a particular GDBusConnection. * unique bus name on a particular GDBusConnection and in a
* particular GMainContext.
* *
* - GDBusMenuGroup represents a particular group on a particular * - GDBusMenuGroup represents a particular group on a particular
* GDBusMenuPath. * GDBusMenuPath.
@@ -60,10 +61,10 @@
* - PathIdentifier and ConstPathIdentifier * - PathIdentifier and ConstPathIdentifier
* - GDBusMenuModelItem * - GDBusMenuModelItem
* *
* PathIdentifier is the triplet of (GDBusConnection, unique name, * PathIdentifier is the 4-tuple of (GMainContext, GDBusConnection,
* object path) that uniquely identifies a particular GDBusMenuPath. * unique name, object path) that uniquely identifies a particular
* It holds ownership on each of these things, so we have a * GDBusMenuPath. It holds ownership on each of these things, so we
* ConstPathIdentifier variant that does not. * have a ConstPathIdentifier variant that does not.
* *
* We have a 3-level hierarchy of hashtables: * We have a 3-level hierarchy of hashtables:
* *
@@ -164,6 +165,7 @@ static GDBusMenuModel * g_dbus_menu_model_get_from_group (GDBusMe
/* PathIdentifier {{{1 */ /* PathIdentifier {{{1 */
typedef struct typedef struct
{ {
GMainContext *context;
GDBusConnection *connection; GDBusConnection *connection;
gchar *bus_name; gchar *bus_name;
gchar *object_path; gchar *object_path;
@@ -171,6 +173,7 @@ typedef struct
typedef const struct typedef const struct
{ {
GMainContext *context;
GDBusConnection *connection; GDBusConnection *connection;
const gchar *bus_name; const gchar *bus_name;
const gchar *object_path; const gchar *object_path;
@@ -199,6 +202,7 @@ path_identifier_equal (gconstpointer a,
static void static void
path_identifier_free (PathIdentifier *id) path_identifier_free (PathIdentifier *id)
{ {
g_main_context_unref (id->context);
g_object_unref (id->connection); g_object_unref (id->connection);
g_free (id->bus_name); g_free (id->bus_name);
g_free (id->object_path); g_free (id->object_path);
@@ -212,6 +216,7 @@ path_identifier_new (ConstPathIdentifier *cid)
PathIdentifier *id; PathIdentifier *id;
id = g_slice_new (PathIdentifier); id = g_slice_new (PathIdentifier);
id->context = g_main_context_ref (cid->context);
id->connection = g_object_ref (cid->connection); id->connection = g_object_ref (cid->connection);
id->bus_name = g_strdup (cid->bus_name); id->bus_name = g_strdup (cid->bus_name);
id->object_path = g_strdup (cid->object_path); id->object_path = g_strdup (cid->object_path);
@@ -305,11 +310,12 @@ g_dbus_menu_path_deactivate (GDBusMenuPath *path)
} }
static GDBusMenuPath * static GDBusMenuPath *
g_dbus_menu_path_get (GDBusConnection *connection, g_dbus_menu_path_get (GMainContext *context,
GDBusConnection *connection,
const gchar *bus_name, const gchar *bus_name,
const gchar *object_path) const gchar *object_path)
{ {
ConstPathIdentifier cid = { connection, bus_name, object_path }; ConstPathIdentifier cid = { context, connection, bus_name, object_path };
GDBusMenuPath *path; GDBusMenuPath *path;
if (g_dbus_menu_paths == NULL) if (g_dbus_menu_paths == NULL)
@@ -646,7 +652,8 @@ g_dbus_menu_group_get_from_path (GDBusMenuPath *path,
} }
static GDBusMenuGroup * static GDBusMenuGroup *
g_dbus_menu_group_get (GDBusConnection *connection, g_dbus_menu_group_get (GMainContext *context,
GDBusConnection *connection,
const gchar *bus_name, const gchar *bus_name,
const gchar *object_path, const gchar *object_path,
guint group_id) guint group_id)
@@ -654,7 +661,7 @@ g_dbus_menu_group_get (GDBusConnection *connection,
GDBusMenuGroup *group; GDBusMenuGroup *group;
GDBusMenuPath *path; GDBusMenuPath *path;
path = g_dbus_menu_path_get (connection, bus_name, object_path); path = g_dbus_menu_path_get (context, connection, bus_name, object_path);
group = g_dbus_menu_group_get_from_path (path, group_id); group = g_dbus_menu_group_get_from_path (path, group_id);
g_dbus_menu_path_unref (path); g_dbus_menu_path_unref (path);
@@ -847,6 +854,12 @@ g_dbus_menu_model_get_from_group (GDBusMenuGroup *group,
* Obtains a #GDBusMenuModel for the menu model which is exported * Obtains a #GDBusMenuModel for the menu model which is exported
* at the given @bus_name and @object_path. * at the given @bus_name and @object_path.
* *
* The thread default main context is taken at the time of this call.
* All signals on the menu model (and any linked models) are reported
* with respect to this context. All calls on the returned menu model
* (and linked models) must also originate from this same context, with
* the thread default main context unchanged.
*
* Returns: (transfer full): a #GDBusMenuModel object. Free with g_object_unref(). * Returns: (transfer full): a #GDBusMenuModel object. Free with g_object_unref().
*/ */
GDBusMenuModel * GDBusMenuModel *
@@ -856,8 +869,13 @@ g_dbus_menu_model_get (GDBusConnection *connection,
{ {
GDBusMenuGroup *group; GDBusMenuGroup *group;
GDBusMenuModel *proxy; GDBusMenuModel *proxy;
GMainContext *context;
group = g_dbus_menu_group_get (connection, bus_name, object_path, 0); context = g_main_context_get_thread_default ();
if (context == NULL)
context = g_main_context_default ();
group = g_dbus_menu_group_get (context, connection, bus_name, object_path, 0);
proxy = g_dbus_menu_model_get_from_group (group, 0); proxy = g_dbus_menu_model_get_from_group (group, 0);
g_dbus_menu_group_unref (group); g_dbus_menu_group_unref (group);