Re: New objects for GLib



Hi Owen,

> > /* Lock and unlock an GAsyncQueue, all functions lock the queue for
> >  * themselves, but in certain cirumstances you want to hold the lock
> >    longer,
> >  * thus you lock the queue, call the *_unlocked functions and unlock it
> >    again
> >  */
> > void          g_async_queue_lock               (GAsyncQueue  *queue);
> > void          g_async_queue_unlock             (GAsyncQueue  *queue);
> 
> Hmmm, is this useful enough to make it worth doubling the API? What are
> the common idioms where you would want to hold the lock over multiple
> operations?

Take e.g. g_threadpool: If I push data into the queue, I first lock it, then I
test its length (telling me, whether a thread to process this data is missing)
and then I start the thread (when it's missing) and push the data into queue
and then I unlock the queue. It it wouldn't lock the queue, another thread
could just attach itself to the queue (thinking, that there is no thread
hitherto) after I found out, that I had to start a thread myself. One could
argue, that I could simply use my own lock, This would however not be released
in a call to g_async_queue_pop and friends. Another option would be to have a
function g_async_queue_mutex, that returns the mutex for that queue and you
could lock it yourself. But that doesn't seem like a big difference. Maybe
having the mutex inside the non-opaque (now GAsyncQueue is fully opaque) part
of GAsyncQueue would be an option.

> > struct _GThreadPool
> > {
> >   GFunc thread_func;
> >   gulong stack_size;
> >   gboolean bound;
> >   GThreadPriority priority;
> >   gboolean exclusive;
> >   gpointer user_data;
> > };
> 
> Is there any reason why this can't just be opaque?

This is only the non-opaque part of the full datatype, which is longer. The
point is, that none of these members might be changed during lifetime of a
thread pool. So they might as well there for the user to see. Adding access
functions for all of them doesn't seem to be a goof idea.

> > GThreadPool*    g_thread_pool_new          (GFunc           thread_func,
> >                                             gint             max_threads,
> >                                             gulong           stack_size,
> >                                             gboolean         bound,
> >                                             GThreadPriority  priority,
> >                                             gboolean         exclusive,
> >                                             gpointer         user_data);
> 
> I don't quite understand exclusive. If exclusive == FALSE, do all
> GThreadPool objects share a larger actual pool of threads?

Yes, thats what happening. So exclusive is only there, because it came almost
for free. I wouldn't suggest using it, only in the case, where speed demands
that at any time there are exactly max_threads threads activt for that pool.
Otherwise threads are reused for thread pools, that need them. I had a
similiar thing in my ORBit-mt (as of version 0.5.0), but I tought, that making
that more general is a good idea. The best thing is the recourse (thread)
sharing by program parts, that doesn't even know of each other.

> In general, these do look like good additions to me.

Ok, I'll make nice test programs and then commit them.
 
> Along similar lines, but a bit more substantial in terms of the work
> necessary, I want to make it possible to have per-thread main loop contexts
> in GLib 1.4.
> 
> The API I'm thinking of for this is that:
> 
>  GMainContext *g_main_context_get_current ();
> 
> Gets the main loop for the current thread.
> 
>  GMainContext *g_main_context_get_default ();
> 
> Gets the default main loop; which would be the main loop in the first thread
> that called g_main_get_default() either explicitely or implicitely. All the
> source. All the source functions are shadowed like:
> 
>  g_main_add_timeout (GMainContext  *main_context,
>                      guint          interval,
>                      GSourceFunc    function,
>                      gpointer       data);
> 
> g_timout_add() becomes implemented as:
> 
>  g_main_add_timeout (g_main_context_get_default(), ...);
> 
> Because iterating the main loop context for a different thread is not
> permissable, g_main_iterate () always iterate the main loop context for the
> current thread, not the default thread.

But what is the policy for the same fd's in different threads then? Leave the
choise of the woken thread to the system? I made the experience, that calling
select in more than one thread doesn't work reliably.

Additionally I would like to be able to ingore some sources for a limited
time. (e.g. while ORBit waits for a response, it doesn't accept events from
the X-windows source).

My idea would be the following.

For ease of use we need a default mainloop. As you propose, all source
functions are shadowed and have a default implemenation that looks just like
now.

You can however define own mainloops with your own (and maybe different)
sources. g_main_iterate is also parametrized by a mainloop (or mainloop
context, you know, what I mean). When it is called, it checkes, whether
another main loop is running. It then adds it context to the global list of
active contexts and wakes up the running mainloop over a pipe (as it is now).
The woken mainloop recognizes the new (longer) list and adjusts itself, as if
both main loop context would be merged. It later wakes up because of an event
and then checks first, whether the event was for the own thread and executes
the according functions. When the event was for another thread, this thread
will be woken (g_cond, g_mutex) and now finds a dispatch_events list inside
its main_loop_context. Those will be dispatched (if wanted) and the game
starts anew. One problem is that the main loop owning thread might switch
between threads frequently then. (Whenever a g_main_iterate is left, the
thread releases the main loop). This sounds, as if it should be slow. I
however think, that there will be only a slight difference for the common
case. It will be more useful however. My proposal would make every thread
think, they are the only thread working with the main loop. Your proposal only
allows the main thread to call g_main_pending and g_main_iterate. I will look
into things and make a proposal soon.

> Note that there is some bad naming problems here since in my initial
> implementation I took over both the GMain and GMainLoop namespaces,
> leading to the
> 
>  g_main_context_create_main_loop ()
> 
> monstrosity.

I would simply break the API to get a saner naming....

Bye,
Sebastian
-- 
Sebastian Wilhelmi                   |            här ovanför alla molnen
mailto:wilhelmi@ira.uka.de           |     är himmlen så förunderligt blå
http://goethe.ira.uka.de/~wilhelmi   |



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