From: David Zeuthen Date: Tue, 7 Sep 2010 15:01:23 +0000 (-0400) Subject: gudev: Deliver ::uevent signal in the thread-default main loop X-Git-Tag: 174~339 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=cbdf255e255adc0f30b40be296fbbf2f3cd2be80 gudev: Deliver ::uevent signal in the thread-default main loop ... that the GUdevClient object was constructed in. This change makes GUdev follow the GLib guidelines and, more importantly, makes it possible to actually use the library in a multi-threaded application. Prior to this patch, signals were emitted in the thread that ran the "default" main loop. Signed-off-by: David Zeuthen --- diff --git a/extras/gudev/gudevclient.c b/extras/gudev/gudevclient.c index f5f7a198d..e829ca314 100644 --- a/extras/gudev/gudevclient.c +++ b/extras/gudev/gudevclient.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- * - * Copyright (C) 2008 David Zeuthen + * Copyright (C) 2008-2010 David Zeuthen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -59,7 +59,7 @@ struct _GUdevClientPrivate { - guint watch_id; + GSource *watch_source; struct udev *udev; struct udev_monitor *monitor; @@ -117,10 +117,10 @@ g_udev_client_finalize (GObject *object) { GUdevClient *client = G_UDEV_CLIENT (object); - if (client->priv->watch_id != 0) + if (client->priv->watch_source != NULL) { - g_source_remove (client->priv->watch_id); - client->priv->watch_id = 0; + g_source_destroy (client->priv->watch_source); + client->priv->watch_source = NULL; } if (client->priv->monitor != NULL) @@ -229,10 +229,16 @@ g_udev_client_constructed (GObject *object) { udev_monitor_enable_receiving (client->priv->monitor); channel = g_io_channel_unix_new (udev_monitor_get_fd (client->priv->monitor)); - client->priv->watch_id = g_io_add_watch (channel, G_IO_IN, monitor_event, client); + client->priv->watch_source = g_io_create_watch (channel, G_IO_IN); g_io_channel_unref (channel); - } else - client->priv->watch_id = NULL; + g_source_set_callback (client->priv->watch_source, (GSourceFunc) monitor_event, client, NULL); + g_source_attach (client->priv->watch_source, g_main_context_get_thread_default ()); + g_source_unref (client->priv->watch_source); + } + else + { + client->priv->watch_source = NULL; + } } if (G_OBJECT_CLASS (g_udev_client_parent_class)->constructed != NULL) @@ -280,6 +286,10 @@ g_udev_client_class_init (GUdevClientClass *klass) * @device: Details about the #GUdevDevice the event is for. * * Emitted when @client receives an uevent. + * + * This signal is emitted in the + * thread-default main loop + * of the thread that @client was created in. */ signals[UEVENT_SIGNAL] = g_signal_new ("uevent", G_TYPE_FROM_CLASS (klass), @@ -310,7 +320,9 @@ g_udev_client_init (GUdevClient *client) * * Constructs a #GUdevClient object that can be used to query * information about devices. Connect to the #GUdevClient::uevent - * signal to listen for uevents. + * signal to listen for uevents. Note that signals are emitted in the + * thread-default main loop + * of the thread that you call this constructor from. * * Returns: A new #GUdevClient object. Free with g_object_unref(). */