Re: Adding custom GDK events
- From: Chris Vine <chris cvine freeserve co uk>
- To: gtkmm-list gnome org
- Cc: Daniel Elstner <daniel kitta googlemail com>, Murray Cumming <murrayc murrayc com>
- Subject: Re: Adding custom GDK events
- Date: Sun, 14 Jan 2007 23:49:52 +0000
On Sunday 14 January 2007 00:38, Chris Vine wrote:
[snip]
> As I think you are saying, this does not in itself ensure memory visibility
> of the callback function pointer or data argument of the idle callback (or
> any other data passed between the threads concerned) and if visibility on
> multi-processor systems is required then some form of memory
> synchronisation (fences or barriers) will be required, typically by means
> of mutex locking of the data.
>
> In practice however I suspect this will be achieved since I am pretty sure
> (although this perhaps should be checked and I will do so next week ...
[snip]
Having now looked at glib/gmain.c it seems to me that g_idle_add() is thread
safe (in the wider sense that it can be used to pass messages to/execute
callbacks in the main loop thread from other threads, as well as in the
narrow sense that the main loop is thread safe). The same appears to apply
to Glib::SignalIdle.
Each GMainContext object has a mutex associated with it which is used to lock
main context operations. g_idle_add_full() creates the new idle source
object and then calls g_source_set_callback(), which assigns (amongst other
things) the function pointer and data arguments to the data members of the
relevant idle source object. At this point the memory representing the
function pointer and data argument is unsynchronised. However it follows
this with a call to g_source_attach() which attaches the idle source object
to the relevant GMainContext object under the mutex lock for that main
context (an acquire and a release).
When the data members of the idle source object are read for dispatching,
g_main_context_dispatch(), which calls g_main_dispatch(), does so under the
same mutex lock, with an acquire and a release. Therefore, when the main
loop thread reads these data members, there has been (a) a release operation
by the signalling thread, and (b) an acquire operation on the same
synchronisation object by the reading thread. Accordingly the memory of the
reading thread will be synchronised with that of the signalling thread to a
condition no earlier than the release instruction being executed, and no out
of order execution of the write will be permitted beyond the point of the
acquire or the point of synchronisation, assuming a platform with these
minimum-level thread safety guarantees. (Actually Posix, in section 4.10,
General Concepts, Memory Synchronization, gives stronger guarantees than
that.)
You know glibmm better than me, but it seems to me that the same would apply
to that. Glib::signal_idle().connect() will create the idle source, and then
call Glib::SignalIdle::connect() on it, which will invoke g_source_attach().
The only thing I notice is that Glib::SignalIdle::connect(), after the call
to g_source_attach(), calls Glib::SourceConnectionNode::install(). I do not
know what that does, but if it is important to dispatch of the slot in the
main loop by the relevant GMainContext object you could always put
LOCK_CONTEXT(context_)/UNLOCK_CONTEXT(context_) around it (or if it makes
sense to put the call to Glib::SourceConnectionNode::install() before the
call to g_source_attach(), put it before the call to g_source_attach()).
As it happens, I recall the PyGTK FAQ recommending using gobject.idle_add() as
the way to pass events to the main thread (although their FAQ page does not
seem to be responding at the moment).
Chris
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]