Re: Threading Problem



On Wednesday 27 September 2006 13:28, Pavel Rojtberg wrote:
> Chris Vine wrote:
> > On Saturday 23 September 2006 12:24, Pavel Rojtberg wrote:
> >> Since I could not find any gtkmm threading tutorial that covers glib
> >> threads with use of gtkmm, I relied on the pygtk documentation:
> >> http://www.async.com.br/faq/pygtk/index.py?req=show&file=faq20.001.htp
> >>
> >> I used Glib::thread_init() instead of gobject.threads_init(), but could
> >> not find any equivalent for gobject.idle_add(), so perhaps that is where
> >> my problems originate from.
> >>
> >> Anyway the problem is that sometimes the interface just stops being
> >> updated while still emmiting events, so I can use the close button.
> >
> > You cannot access GTK+ in more than one thread without using the global
> > GDK lock (and you cannot do it all, with or without the GDK lock, under
> > windows).
> >
> > This explains how GTK+ interacts with glib threads:
> > http://developer.gnome.org/doc/API/2.0/gdk/gdk-Threads.html
> >
> > To post events using gtkmm, see Glib::Dispatcher.  You can also use the
> > raw C function g_idle_add() if you wish, but this is not wrapped in
> > glibmm (presumably because glibmm provides Glib::Dispatcher, which glib
> > does not). Either of these will execute the callback in the thread in
> > which the main program loop (and by default GTK+) execute, so avoiding
> > the need to use the GDK global lock.  If you use g_idle_add(), make sure
> > the handler returns FALSE so that it only fires once.
> >
> > Chris
>
> thanks for your reply. meanwhile I asked on the IRC and came out with
> the Glib::signal_idle().connect(), which is as far as I can see the
> equivalent of g_idle_add().
>
> But while trying to use it I noticed that sigc++ does not work with
> Glib::RefPtr - I just could not bind Gtk::TextBuffer::insert without a
> wrapper function...
>
> Anyway which implementation would hou consider as the cleaner one
> signal_idle or dispatcher?

Both Glib::Dispatcher and Glib::SignalIdle should work similarly.  
Glib::Dispatcher uses a pipe under the covers, as does Glib::SignalIdle when 
used with Unix-like systems, although with different priorities in the main 
program loop, which will probably not make any difference in practice.  I do 
not know if Glib::Dispatcher works with windows if you are interested in 
portablility, although Glib::SignalIdle does.  The important thing with 
Glib::SignalIdle is to remember to have the handler return false.  Returning 
true can turn your main loop into a busy wait.

In relation to binding arguments, there are apparently some difficulties in 
storing a smart pointer in a slot - see 
http://mail.gnome.org/archives/libsigc-list/2006-August/msg00008.html , which 
probably includes storing Glib::RefPtr objects in them.  Whether it applies 
when you bind the RefPtr to the slot as an argument with sigc::bind I do not 
know.  If that is a problem you can push the argument onto a std::queue (say 
in class scope) and pop it off again in the handler, although that is less 
appealing aesthetically.

In the threading context you also need to consider memory visibility of the 
argument passed from one thread to the other - it seems very unlikely that 
shunting bytes via a pipe to trigger the main loop (which is what happens 
under the covers) is not going to cause memory to sync up, but POSIX doesn't 
guarantee it - to get that guarantee you need to have a release in the 
sending thread and an acquire in the receiving one, typically by using a 
mutex.  Using a std::queue would deal with this automatically as you would in 
any event protect access to the queue with a mutex in this use.

In practice C programmers do the equivalent with g_idle_add() and GAsyncQueue 
(for the data).  This is probably also what PyGTK uses to bind arguments.  
With g_idle_add() you can also pass the data as the data argument of that 
function, but then you would have to provide your own locking in 
multi-threaded use. You could of course use the C functions in your C++ code 
if you want.  They are less opaque and it is easier to see how locking and 
visibility issues will work out than when wrapped for C++.

Chris




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]