Re: Handling Unix signals in a GTK+ application

Freddie Unpenstein wrote:
Going back to your original point, it is definitely not a
"busy wait".

I just rolled together a quick test...  A GTK main loop running two "sources".

First an "event source" created using g_timeout_add() that prints the current count each second, and halting 
the program (via gtk_main_quit() ) after the 10th count.

Second, an idle event crated though g_idle_add() that simply increments said counter and returns true to 
repeat (similar to what you'd have watching for a flag indicating a Unix signal had occured).

The program ran for 10 seconds, giving counts of:
** Message: Ticker Tocker...  9 -> 160565
** Message: Ticker Tocker...  8 -> 343367
** Message: Ticker Tocker...  7 -> 545729
** Message: Ticker Tocker...  6 -> 703564
** Message: Ticker Tocker...  5 -> 856554
** Message: Ticker Tocker...  4 -> 1018223
** Message: Ticker Tocker...  3 -> 1219280
** Message: Ticker Tocker...  2 -> 1390704
** Message: Ticker Tocker...  1 -> 1548533

My CPU usage graph applet showed a 100% CPU burn during that time, however oddly the output of the system 
"time" command showed:
   real:10.587s user:2.172s sys:7.224s
If that means anything useful.  I'm guessing from that that the program is spending a good deal of its time 
in select(), with a zero timeout (causing it to return immediately each time).

That's well over 1548533 executions (I forgot to print the counter after the 10th second) of the idle 
callback, or 172059 calls to the idler function per second.

Personally, I'd call that a busy wait.

Its not a busy wait; your idle handler has never returned FALSE;
so whenever your application is idle (i.e. all the time) then
the idle handler will run; whether it be the gmain.c code or the
code in poll( /* timeout == 0 */ ) that decided to return directly.

If you call g_idle_add() from another thread or from a signal; the
g_idle_add() will either:
    o Just queue an idle handler if the loop is busy
    o Queue an idle handler and wakeup the loop if the loop is sleeping

Which BTW; is done by writing an arbitrary charachter into a pipe()
that will force the mainloop out of poll() if its sleeping.

From what I see above; this is all clean "event based" programming
(no-one is executing for no reason).

An interesting test though; as someone already mentioned (and may have
been misunderstood)... is what if the loop is never idle ?
(not "what if the loop seldom runs ?")... what if you set your timer
to execute every "1" millisec... I would assume that since glib
could never meet this requirement; the timeout would run "all the time"
and the idle handler would "never run".

Essentially; using write(2)/pipe(2) or using g_idle_add() is the same;
except that write/pipe is a little more complex (have to setup an
IOChannel on the recieving end) and more failsafe (IO will not be
treated like an idle... it will have a good priority and be sure to
execute... also it wont randomly crash like g_idle_add() will when
running where g_thread_supported == FALSE).

Maybe a high-priority timeout/idle where your app asserts that
g_thread_supported() would be the safest/easiest.


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