Re: Thread specific data for GLib




Sebastian Wilhelmi <wilhelmi@ira.uka.de> writes:

> 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.
 
> [ 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. 

> 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)

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

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.

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.

Netscape generally uses constructors to set up the
the TSD indices; using pthreads you can use 
pthread_once(). 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.

Regards,
                              Owen

=======
#define g_private_new(destructor) \
  G_USE_PRIVATE_FUNC(private_new,NULL,(destructor))
#define g_private_get(private) \
  G_USE_PRIVATE_FUNC(private_get,((gpointer)private),(private))
#define g_private_set(private,value) \
  G_USE_PRIVATE_FUNC(private_set,(void)(((gpointer)private)=(value)), \
		     (private,value))

struct _GStaticPrivate
{
  /* constructor is called by g_private_get */
  GNewFunc constructor; 
  /* destructor is called, when the thread ends */
  GDestroyNotify destructor;
  /* if size is non-zero, constructor is taken to be g_malloc0(size)
     and destructor is g_free */
  guint          size;
  /* do not use the following element */
  guint          id;
};

#define G_STATIC_PRIVATE_INIT_FOR_SIZE(size) \
  { NULL, NULL, size, 0 }

#define G_STATIC_PRIVATE_INIT_FOR_TYPE(constructor,destructor) \
  { constructor, destructor, 0, 0 }

GStaticPrivate* g_static_private_new_for_size(guint size);
GStaticPrivate* g_static_private_new_for_type(GNewFunc constructor, 
					      GDestroyNotify destructor);
gpointer g_static_private_get(GStaticPrivate* private );
void g_static_private_set(GStaticPrivate* private, gpointer value );
void g_static_private_free(GStaticPrivate* private);
=======



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