g_idle handlers in unexpected sequences

When you specify glib idle callbacks to g_idle_add_full() with different priorities, there is no guarantee that they will be called in the order that you added them. But it’s normal that you’d want, for instance, progress callbacks to have a lower priority than the callback that does the work itself. But you probably need to know when the last callback has been called (so you can release state information), and you probably don’t want to show progress information after the work has actually finished.

I added this generic TnyIdleStopper API to tinymail to help us avoid this problem: It’s a kind of a weak-ref smartpointer thing. It seems to stop the crash, and passes the valgrind test, but I worry that there’s a far simpler solution that I’m overlooking.

8 thoughts on “g_idle handlers in unexpected sequences

  1. The component which encapsulates the work and raises the callback change events should raise a signal when the last callback is invoked. The data included with this signal would indicate that it was the last signal, that work had completed or been canceled. The catcher of this signal should be responsible for releasing the resources involved in doing the work, so as not to race.

  2. Shouldn’t destroy be the last one? Shouldn’t that be guaranteed? If not I’d imagine it would be a bug.

  3. You mean the destroy callback specified to g_idle_add_full() ? But which destroy is last if you call g_idle_add_full() twice with different priorities?

  4. Hmm. Never noticed that. I think what I meant is that you wouldn’t use g_idle_add_full() with a GSourceFunc pointing into the consumer’s code, but into the encapsulation. You would then, from the encapsulation, create some sort of structure which represented the state of the operation, and pass that to the user’s callback. You’d probably do this by exposing it as a signal on the encapsulation, which the consumer would listen to. That signal would deliver the structure. This structure would also convey the progress, such as a percentage, or something.

  5. You could also expose two signals from your object, one for progress, one for state changes. This might form a cleaner API.

  6. Jerome, yes this is all about fixing the implementation so that the outer API behaves as expected. For instance, progress callbacks are not called after the main callback has indicated that the operation has finished.

Comments are closed.