Re: Changes to the GLib main loop [ GMainLoop ]
- From: Owen Taylor <otaylor redhat com>
- To: Sebastian Wilhelmi <wilhelmi ira uka de>
- Cc: Gtk Development List <gtk-devel-list gnome org>
- Subject: Re: Changes to the GLib main loop [ GMainLoop ]
- Date: 30 Jun 2001 14:58:11 -0400
Owen Taylor <otaylor redhat com> writes:
> Sebastian Wilhelmi <wilhelmi ira uka de> writes:
>
> > > > Ok, but that could be optimized away by also telling
> > > > g_main_context_iterate, whether it was called from g_main_loop_run or
> > > > not only signalling other threads, when it was not run from
> > > > g_main_loop_run. For calls not done from g_main_loop_run it would
> > > > still need to be called, because of the scenario outlined above (the
> > > > thread A and B thingy)
> > >
> > > This doesn't work because the thread needs to be woken up to check for
> > > loop->is_running, even before the main loop stops running its loop.
> > >
> > > (Remember, what I want to be able to do here is use main loop to wait
> > > for a modal dialog being closed, whether or not the dialog is being
> > > shown from the main thread.)
> >
> > Ah, I see, but the solution to this is calling g_cond_broadcast in
> > g_main_loop_quit. So I think the following is enough:
> >
> > * Make g_main_context_iterate call g_cond_broadcast only when not called
> > from g_main_loop_run.
> > * Make g_main_loop_quit call g_cond_broadcast.
>
> Isn't the right way to express this is "broadcast when releasing
> ownership of the context?"
>
> Other than this, yes this approach works pretty well. (Main problem
> is if you have a bunch threads waiting for ownership, they all
> wake up and try to get ownership)
Turns out, when I tried to actually make GMainLoop works this
way completely using the public interfaces, it doesn't work.
There is an inherent race condition, coming from the
general principle:
- if you want to wait for a condition with a condition variable,
then you must test the condition, and then call g_cond_wait()
without ever releasing the accompanying mutex.
That is:
while (loop->is_running || !got_ownership)
{
UNLOCK_LOOP (loop);
got_ownership = g_main_context_wait (context);
LOCK_LOOP (loop);
}
Is inherently broken, because loop->is_running can become
FALSE betweeen the point where it is tested, and
g_cond_wait (loop->cond) is called.
So, I think what I'm going to do is:
g_main_context_wait (GMainContext *context,
GCond *cond,
GMutex *mutex);
Which (called holding mutex)
a) adds the cond to a list of condition variables waiting
on the context
b) Calls g_cond_wait(cond,mutex)
And then, have g_main_context_release() signal exactly
one of the condition variables waiting on the context.
It should still possible to reuse context->cond for all loops
this way with a few extra checks in the implementation.
Regards,
Owen
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]