Re: to many invalidate_rect calls freezes window



On Thu, 21 May 2009 22:58:53 +0200
buergi <pat_buergi124 gmx de> wrote:

> perhaps someone could explain how the Dispatcher works, not in code
> but what happens behind the scenes. when i emit the dispatcher in the
> worker thread, when does the connected function in the main thread get
> executed. will it be called by the signal handling in the gtk main
> loop?
> 
> the only problem is that i cannot pass arguments over a
> Glib::Dispatcher neither return values are supported (of course since
> the dispatcher is asynchronously). I also need to pass the content of
> variables from one thread to the other.
> What about a SigCX::ThreadTunnel?

When you emit on a Glib::Dispatcher object, in unix-like OSs it
sends a key (actually it's the dispatcher's address) on a pipe which
has a watch on the pipe's file descriptor attached to the main program
event loop which executes in the main GUI thread.  On windows it signals
a windows event object, likewise plumbed into the main loop.

The slot(s) you have connected to the Dispatcher object will then be
executed in the main GUI thread whenever you emit on the dispatcher,
which is what you want.  It will be executed by the main loop on its
next event iteration.  You don't need to worry about "when" (it will be
"shortly after, depending on what else is in the event queue") - if you
do need to worry about it, threads are probably not the answer to the
problem you are programming for.

To pass arguments using Glib::Dispatcher, except in very simple cases
you will probably need something like an asynchronous queue.  glibmm
doesn't have one, but it is relatively straightforward to make your own
based on std::queue and Glib::Mutex, and I can send the one I use if it
helps - there are certain subtleties to be observed if you want the
queue to retain strong exception safety.

Alternatively you can use g_idle_add() or g_idle_add_full(), which are
thread safe as with the rest of glib, and these also add events, in the
form of a callback, to the event queue in the main loop. The callback
function should strictly speaking have C linkage, although in fact g++
allows you to use static member functions which have C++ linkage (but
if you want standards conformance you should use a callback function
declared extern C, and make it a friend if you need it to have
private/protected class access). You can pass any arguments you like as
the data argument to g_idle_add() - typically it might just be the
address of the class object that you want the callback to be able to
access - but if it is more than that you will probably need to pass a
data struct by address with the data allocated on the heap and freed in
the callback once finished with. The callback function should return
false so that it only executes once.

Using g_idle_add() is the most directly analogous approach to using
windows events, passing messages to the the windows GDI for drawing
(basically it works exactly the same way). Don't be fooled by the name,
which was a poor choice - if you use g_idle_add_full() you can choose
any priority in the event queue you like.  The disadvantage is that you
do not get the safety arising from automatic slot disconnection when
using Glib::Dispatcher with slots representing methods of classes
deriving from sigc::trackable.  With g_idle_add(), it is for you to
make sure that when the main loop executes the callback, any class
object it is accessing still exists.  On the other hand you don't have
to worry about the validity of a Glib::Dispatcher object, which must
exist when a slot is executed via a dispatcher (the main loop tries to
look up the dispatcher object on slot execution for obvious reasons).

Note that you cannot use Glib::signal_idle() from glibmm for this, as
unfortunately it is not thread safe.

I've never used SigCX but I think it also uses pipes, connected to the
main loop.

Chris



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