Re: Question about event loops




James Moody <james@cr836502-a.slnt1.on.wave.home.com> writes:

> Hello all...
> 
> I'm currently evaluating GTK+ for use in a project that I'm involved with.
> Unfortunately, I can't divulge the details, so forgive me if this post
> is too vague...
> 
> I have a question about event processing. In my potential use of GTK,
> calling gtk_main() is not acceptable. I need to be able to process
> events that are unrelated to GTK in the same thread, so what would be
> ideal for me is a loop that I can use which will accomplish the same
> thing yet provide me with time to do my alternative event processing.
> 
> The basic idea of the loop would be
> while (events pending) {
> 	process some gtk events
> 	do some of my own event processing
> 	sleep maybe?
> }
> 
> In Havoc Pennington's book, I see
> while (gtk_events_pending())
>     gtk_main_iteration();
> 
> which would seem to suit my needs, but I thought I'd ask to make sure.
>
> Does the code quoted above assume that I'm already in at least one
> level of gtk_main() calls? Or is it intended to be used on its own? 
> (The context of the example in the book where the above code came from
> involved processing events while in a lengthy callback, and gtk_main()
> was already running, which is why I wasn't sure).

Basically, all gtk_main() does is call g_main_iterate() repeatedly
until gtk_quit() is called; so things will work fine if you call
g_main_iteration() directly.  (gtk_main_iteration() is wrapper around
this call that is provided backwards compatibility with older versions
of GTK+.)

The tricky thing is your "sleep maybe?". As long as you
want to eat CPU, then doing:

 while (1) 
  {
    g_main_iteration(FALSE);
    
    /* Do your stuff */
  }

works fine. (The 'FALSE' means - return immediately if there
is nothing to do.) But there is no way of getting out enough
information to figure out when there will next be something
for GTK+ to do. (You can't retrieve the file descriptors
it is waiting on or the time until the next timeout it
needs to process.)

If you aren't using threads, then a single entity needs to
be responsible for handling all waiting. GLib does not like
other people to handle the waiting, so you basically need
to let GLib wait for you. This doesn't mean you have to
use GTK+'s timers and IO handlers. You can do things like:

 /* Set up an IO watch, so that GLib wakes up whenever there
  * is input waiting on a given file descriptor. Using
  * gtk_true here means that this watch will always remain.
  */
 GIOChannel *channel = g_io_channel_unix_new (my_fd);
 g_io_add_watch (channel, G_IO_IN | G_IO_HUP, (GIOFunc)gtk_true, NULL);
 g_io_channel_unref (channel);

 while (1) 
  {
    /* Process all pending events */
    while (g_main_iterate (FALSE)
      /* Nothing */;

    /* Add a timeout, so that we don't sleep for more than
     * time_to_sleep milliseconds
     */
    g_timer_add (time_to_sleep, gtk_false, NULL);
    g_main_iterate (TRUE);

    /* do what you need to do */
     [...]
  }

but it is hard to just use a select() yourself and drive
GTK+ off of that.

> Before you ask the obvious "why are you doing this? Just call gtk_main()",
> I'll say that this is not a simple GTK application, and having done the
> same thing on other platforms, we have a pretty good idea of the type of
> solution we need for this particular project. The documentation for the
> event functions is just sketchy at best and I need more information on
> what the above calls are intended to do, specifically.

You should definitely look at:

 http://developer.gnome.org/doc/API/glib/glib-the-main-event-loop.html

if you haven't already. It isn't a tutorial, and doesn't
give a high-level description of the interaction with GTK+
but it does document all the functions reasonably well.

Also, if you have very little flexibility in how to handle your
main loop, sometimes threads _are_ the way to go to integrate
it with GTK+. (Of course, with the usual caveats about 
threads.)

Regards,
                                       Owen



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