Re: Thread specific data for GLib



Hi, Owen

> > > While testing out the thread-safety patches to GLib,
> > > I ran into one problem that I don't see how to
> > > solve without adding thread-specific data to our
> > > set of primitives -
> >
> > Ah, I havn't seen that yet, but I already wrote "MT safe" into the 
> > header,
> > makes me wonder, how reliable my other "MT safe" remarks are ;-)
> 
> Well, once we figure out the basics, I'll make a careful
> read-through to try and find holes.
> 
> This particular problem though was pretty simple to find -
> since it was static data that was neither per-thread
> or locked.

Yes, I also looked for static keywords, but I ran across this particular
one, because it was so nice hidden between the static functions ;-(

> > [ snip ]
> > > It would then be easy to provide,
> > > on top of that, a more "G-ish" interface that provided
> > > the optional ability to associate data with character
> > > keys instead of numeric ID's. (I.e., something along
> > > the lines of GDataSet / GDataList)
> >
> > Thats not good, that is asking for trouble (is this case it is asking 
> > for
> > name space collisions).
> 
> And functions are asking for trouble because their is only
> a single namespace...
>
> Using prefixes in ones key should keep that from being a
> problem.

Yes, sure, but for functions you get the error at the latest at link time,
whereas this can (and consequently will) lead to silent failure (not even
a run-time error is seen, it just fails). The same does not apply to
datasets and datalists, as they are either bound to a particular address
or dedicated objects. furthermore this approach wouldn't make it faster to
access private data, so why not use a plain old external or static objects
for the identification of private data.
 
> > I have however added a (I think) quite G-ish
> > addition, that again can be statically initialized, it of course needs a
> > mutex call there, but that is an acaptable cost, because you gain a 
> > quite
> > nice interface. You can alos set a constuctor, that is used every time 
> > the
> > private data is read and would be NULL. and you can destroy a key and 
> > all
> > data related to it (thats not possible under either solaris or posix).
> > You'll soon find a patch in
> >
> > ftp.gtk.org/incoming/glib-wilhelmi-981207.patch*
> >
> > Bye,
> > Sebastian
> >
> > PS.: There still are some rough edges, but in general I am quite content
> > with my solution. ;-) (so at least someone is)
> 
> For other people's reference the API is below. IMO, it is
> neither terribly G'ish, nor like any other thread-private
> data I've seen. That isn't to say it is bad, just a little
> unusual. (The use of integer indices for thread specific
> data seems to be pretty universal)

Yes, it is, but again, it always causes much headache for people using
thread private data to allocate those integer indices, especially when
programming libraries. And isn't it glib's purpose to minimize the
programmers headache?

> [ The no-threads part of g_private_set needs fixing
>   in any case ... lvalue casts aren't standard C ]

oh, yes, I forgot. trivial to fix though.

> In general, I'd like to stick to something a lot closer
> to the metal. All this StaticPrivate stuff may, IMO,
> is really over-complicated, and may not match the
> needs of the application.

It is complicated for two reasons:

1) it has an own managment of data, this is to provide the possibility to
   destroy all data connected to a key. This can't be done on either
solaris
   or posix.
2) it provides the additional parameter constructor, that is called,
   whenever the data, that would be returned is NULL. This is
   extremly practical, because most of the time you'll find yourself doing
   something like this:

   if( (data = g_private_get( key ) ) == NULL )
      g_private_set( key, data = g_new0(blablub,1) ); 

   This addition doesn't impose much overhead (it's just one comparison
for
   every call, compared to the mutex lock it's just nothing).

> The question, though, is how to provide a convenient
> interface to getting a unique thread index to use
> for your a bit of static data, without requiring
> locking on each fetch of the static data.

That simply is not possible without magic (like constructors and the
like). Period. (Regarding pthread_once see below)
 
> Netscape generally uses constructors to set up the
> the TSD indices; using pthreads you can use
> pthread_once(). 

here is a small test, I've done:
pthread_mutex need 1031 nanoseconds for enter/exit pair.
pthread_once needs 1327 nanoseconds for call.
pthread_getspecific needs 3253 nanoseconds for call.
pthread_setspecific needs 467 nanoseconds for call.

The program is attached for anyone to try it on his/her platform. I really
think, its rediculous, that pthread_setspecific is more than 5 times
faster than pthread_getspecific, and still more than twice as fast as a
pthread_mutex enter/exit pair. as you see pthread_once is slower than a
pthread_mutex enter/exit pair. The last should actually also hold true on
linux, I suppose.

> I'm not quite sure what the right
> approach is for GLib, but at least for gmessage.c,
> it's easy, since we are already locking a mutex,
> we can just use that to guard the initialization.

yes, but we are looking for a general approach, and such GStaticPrivate is
not that bad, if you want maximum speed, you could still use the GPrivate
interface. 

Bye,
Sebastian
-- 
+--------------============####################============--------------+
| Sebastian Wilhelmi, Institute for Computer Design and Fault Tolerance, |
| University of Karlsruhe;  Building 20.20, Room 263,  D-76128 Karlsruhe |
| mail: wilhelmi@ira.uka.de;  fax: +49 721 370455;  fon: +49 721 6084353 |
+-----------------> http://goethe.ira.uka.de/~wilhelmi <-----------------+

ptest.c



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