GLib "next cycle" update
- From: Ryan Lortie <desrt desrt ca>
- To: gtk-devel-list gnome org
- Subject: GLib "next cycle" update
- Date: Sun, 18 Sep 2011 13:11:36 -0400
I've torn through a great deal of what I wrote about in "GLib plans for
next cycle" email. Changes are on master.
I'm presently working on the "wip/mutexes" branch. There are two
somewhat-related efforts on this branch:
First, I'm trying to slay bug #70598 by deprecating GStaticMutex and
creating a GMutex that you can do:
GMutex mutex = G_MUTEX_INIT;
and the same for GCond while we're at it and GPrivate to a somewhat more
limited extent (for GLib internal use only, at present).
The benefit here is that we can have mutexes and condition variables
without any memory allocation at all, which is good for avoiding
initialisation dependency cycles inside libglib (where gmem depends on a
GMutex, but GMutexes are allocated with gmem, for example).
The most controversial patch here so far is this one:
which could be seen as causing an ABI Break for glib-using libraries
that export locks defined as a G_DEFINE_LOCK as part of their public
ABI. That's unlikely.
It's also an API (but not ABI) break if you were trying to use the
undocumented G_LOCK_NAME macro (as GCancellable is doing, and thus
needed to be fixed). This could be considered a bug in the application
and is easy to fix.
Second, I'm trying to nuke the few remaining reasons that
g_thread_init() is required at all. The static GMutex/GCond/GPrivate
code is making this a bit easier, but there are some performance
In particular, in the 'likely' case, gslice goes to substantial pains to
avoid any cross-thread synchronisation. This is incompatible with
implicit initialisation in threaded contexts. There are approximately
three ways that I can think of to address this:
- suck it up and do a proper thread-safe implicit initialisation
This is probably no performance decrease on Intel (where we have
somewhat strict ordering guarantees and can probably avoid a fence).
It will definitely require fences on some platforms, however.
- initialise on the first g_thread_create() call
This seems like it would avoid any chance of races in gslice
initialisation but it means that we wouldn't be safe with respect to
threads that weren't created by GLib (like some asynchronous
libraries do for callbacks).
- use a __attribute__((constructor)) approach
I have a patch here to introduce this concept as a quick hack:
and two uses of it:
For the record, I think that this is a somewhat inelegant solution.
Maybe it's our best choice, though, given the constraints. I know
some others want to make use of this, and maybe we could even
consider making the API public (and cleaning it up).
I have doubts that we can ever support this everywhere in a portable
way but we can probably get pretty reasonable coverage. Matthias
also raised some concern about the undefined order in which the
constructors could be called (which means that we might have to
refrain from calling gslice from other constructors, for example,
since gslice may not have been initialised yet).
A couple of solutions to that:
- use the (priority) field of GCC
- use internal rigging to ensure dependent inits are called first
or just use one big initialisation function that does it in the
- make the ENSURE macro do a thread-unsafe initialisation check
even in the case that we support constructors so that we catch
these sorts of problems. This would be safe* because the ctors
are always running at a time when we can be guaranteed the code
is only being accessed by a single thread.
* I can, in theory, imagine some truly absurd scenarios where this may
not be true. They involve a CPU speculating reads from a library for
which dlopen() has yet to return a handle on another CPU. I'm am not
] [Thread Prev