Re: Changes to the GLib main loop [ g_main_iterate() ]



Hi Owen

> > I don't think the programmer expects that. I think
> >
> > while (g_main_context_pending(context))
> >   g_main_context_iteration(context, may_block)
> >
> > is a idiom for saying "if there are any pending updates for e.g. GTk
> > windows, do them, before I continue a long computation".
> 
> Hmmm, so what you are saying is that you think that this idiom,
> preferably written as:
> 
>   while (g_main_context_iteration (context, FALSE))
>     /* nothing */;
> 
> Is saying "if nobody is handling events currently, then handle anything
> pending." And the consider if any instances of g_main_run() are running,
> someone is handling events.
> 
> This doesn't correspond to experience - every time that someone has
> asked about iterating the main loop from the other thread, they have
> been interested in handling GUI events while the main loop is blocking.
> 
> Now it may be the case that having g_main_context_iteration (context,
> FALSE); do nothing and return FALSE if the context is owned elsewhere is
> the best we can do and better than what we currently do - which
> is to warn and do nothing. But I don't think it what people expect
> or want.

Possibly, but as you said: it's the best we can do and better than what we
currently do.

> My other fear would be that people would write:
> 
>  while (i_dont_have_a_message)
>    g_main_context_iteration (context, TRUE);
> 
> Which, in a non-owner thread is hideously expensive. Just like the
> case of the g_main_context_run(). 

I don't think it is that expensive. Per iteration it costs one
g_cond_broadcast in the owning thread, one context switch, and then the thread
falls asleep again. Given that this happens only when a new event arives, it
isn't that bad.

> > And indeed these updates are done, but in another thread, so FALSE
> > is returned. and the loop is not entered. Of course the other thread
> > might block itself in a long computation, but again it might call
> > the above two lines from time to time and it still works.
> 
> I'm not sure what the definition of "work" is. If you mean "doesn't
> produce warnings", then sure. If you mean, "cause anything useful
> to be done", I don't see how it does that.

It finds context->owner == self and goes into the normal iteration, but not
resetting the owner, when leaving. So that works.

> The common case is that one thread is inside a g_main_loop_run() for
> the entire execution time of the program. Either that thread
> is already processing events, or it is blocking in a computation.
> Either way g_main_context_iteration() in another thread doesn't
> do any good.

No, it doesn't do any good, but it doesn't hurt either. We can't (at least not
easily, but I'm actually not even sure, we can at all) provide a system, where
you could call g_main_context_iterate from multiple threads concurrently and
still get the dispatching done in all threads. But we can enable programmers
to use the known main loop idioms without caring about the current thread vs.
the thread of the context. I actually think, it's pretty clear, if documented
right.

> Past experience says that it _is_ suprising that g_main_iteration()
> in another thread doesn't handle events in that other thread when
> the main is blocking.
> 
> So, in summary:
> 
>  * I don't see (with your scheme) g_main_context_iteration() from
>    another thread as being useful, though g_main_context_run()
>    is.

It's not useful to call this deliberately in another thread. It just makes
using it independend of the calling thread. 

>  * However, if making g_main_context_iteration() from another
>    thread not warn is the price of enabling:
> 
>     - Moving a loop between threads
>     - Allowing creating a loop before the thread
> 
>    Then perhaps we should do that, and just be prepared for
>    some questions on gtk-list ;-)

I would say so.

> > > Possibly the right behavior is for the threads to dispatch requests
> > > round robin, and for the first free thread to start a new cycle,
> > > ignoring sources currently being dispatched. This would need
> > > _very_ careful definition, and the combination of this and
> > > recursion within threads presents a highly complex situation.
> >
> > That is true, it sound like a implementation nightmare with no real
> > benefit. If the user want's to dispatch certain events to other
> > threads, s/he should use GAsyncQueue or better yet GThreadPool, which
> > is just for doing that.
> 
> I'd tend to agree that the structure should be:
> 
>  * One thread handles incoming events, and dispatches all slow
>    operations to other threads.
> 
> It's not the only way people try to write things, but probably we
> just need to educate people.

Yes. Also I don't think, this is something that people will often use in
normal applications. So that shouldn't be a problem.

Bye,
Sebastian
-- 
Sebastian Wilhelmi
mailto:wilhelmi ira uka de
http://goethe.ira.uka.de/~wilhelmi




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