Today's Hot Hack
Today I got fed up of writing yet another GQueue and idle function to perform tasks incrementally in the background, with all of the bookkeeping that needs to be done. So, I wrote taku_idle_queue_add.
Using it is simple, create a GQueue and then call taku_idle_queue_add, passing the queue and a callback function. When the queue has items in it, the callback gets called. Easy! Just remember not to return FALSE from the callback unless you are sure the queue will never be used again.
I'd appreciate anyone who knows GSource programming in detail to review the code. Maybe I should even try and get this into Glib?
NP: Cliqhop IDM, Soma.fm
gint* is not safe on amd64 or ia64.
prepare (GSource source, gint timeout)
In which case you are wrong. timeout is a pointer to an integer.
if (!callback) {
g_warning ("Queue source dispatched without callback\n"
"You must call g_source_set_callback().");
return FALSE;
}
by :
g_return_val_if_fail (callback != NULL, FALSE);
and made the taku_idle_queue_add complain if the function wasn't correct.
For many apps this might be fine, but if you want your application to update even when the user isn't actively interacting with it (moving mouse, typing etc) it may be a problem.
The approach I took in Hotwire for this was to have a queue wrapper where the calling thread adds an idle handler. Check out IterableQueue here:
http://hotwire-shell.googlecode.com/svn/trunk/hotwire/async.py
Disadvantage is that it requires an extra mutex and overhead.
Colin: I was wondering who would notice that. :) Yes, if the queue is manipulated without any GTK+ events then the callback isn't fired until something happens. As "something happens" is quite loose, and in my application the queue is manipulated on startup and when the style changes, this isn't a problem for me. Obviously its a show-stopper for some applications.
Ideally, you'd want to attach a pollfd to the source to wake up the main loop (assuming you have an fd), or you could have your own queue_push function that wakes up the main loop explicitly.
Ross, you may want to use a GAsyncQueue if you plan to use it for off-thread.
http://svn.gnome.org/viewvc/ekiga/trunk/lib/engine/framework/runtime-glib.cpp?view=markup
might be of interest too.