Re: closure threading issues



> hey owen, havoc, sebastian, kenelson,
> 
> with the recent addition of g_signal_newc() that internally creates
> a closure, we can theoretically have objects that don't live under
> a common global lock (like for instance Gtk ones) sharing a closure.
> closures themselves provide no extra guarding code wrg thread safety,
> and i'd rather leave it at that, since in general clashes here
> shouldn't occour and locks would prolly just slow down things
> (and the closure code is sufficiently complex already).

In other words you are aiming for STL like thread protection.
Under STL global shared resources are internally protected (like
the main type hash table), but all visible types must have 
an associated external lock.  That means if two threads are
working on a list, they must have a lock shared between them
to prevent overlapping accesses.
 
> however, as mentioned above, that requires users to access objects
> of the same class only from within a single common lock, and as
> we move away from gtk/gdk objects, i'm not sure that requirement
> holds true anymore.
> 
> we'll have to choose either of:
> 1) the user has to provide threading guards at least per-class
>    that he uses objects off (i think that will break at pure
>    G_TYPE_OBJECT level already)
> 2) users will definitely use objects of the same class from
>    different threads (that's what applies to G_TYPE_OBJECT already
>    though we could make that an ugly exception with some closure
>    hacks)
> 
> i guess the outcome of this is (2) and that in turns requires proper
> gclosure.c locking that i don't feel overly comfortable with.
> usign one global closure lock is prone to cause a lot of runtime
> collisions, hurting performance, while using per-closure locks
> will considerably bloat memory.

I am currently about this same point in libsigc++.  But as I
am only beginning work on it I can't be all that much help.
Per closure locks are definitely a pain and the performance lose
likely doesn't justify it.  

My current working solution is to use atomics on linux for the 
reference counters.  This unfortunately rules out packed 
ints.  Thus switching to atomics will increase the memory size
of the closures as the bit flags and the up/down fields must 
be separated.  Additionally, I have list operations, but as these
only happen on connection and disconnection I can afford to 
use one global hidden internal lock to protect them.  Also
there is no user supplied procedures in this so I can keep the
locks for the entire operation without chopping things up too
much on the locking.  For machines without atomics, I plan to
use spinlocks and barring that mutexes.  

Unfortunately, gtk+ has global lists of emissions which must
be maintained on an emit.  This means thread locks internally or
a global lock of the closure system is required.  (I avoided this
in libsigc++ because I have no global resources).  That means I can't
do an emission stop without specifying the signal.  And shared closure or 
signal under libsigc++ will need to have its own extern lock, or
use of an locking adaptor.  (A closure which points to another closure
which assures locking.)

--Karl





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