Boost logo

Boost :

From: William E. Kempf (wekempf_at_[hidden])
Date: 2003-06-02 10:58:42


Chuck Messenger said:
> I've been experimenting with the thread lib. I found a bug related in
> some way to thread_specific_storage (tss). In particular, I #ifdef'd
> all the tss stuff out, using native pthread calls instead, and
> everything worked as expected.
>
> So, I went back through, trying to determine what could be going on.
> I'm using tss to store a pointer to a thread-wide structure.
>
> thread_specific_ptr<mythread*> current_thread;
>
> mythread *mythread_get() {
> return *(current_thread.get());
> }
>
> static int init() {
> // Need to initialize thread local storage for main thread
>
> // XXX I'd like to put something here to ensure that
> // current_thread has been constructed. But what?
>
> current_thread.reset(new mythread *);
> *(current_thread.get()) = new mythread;
>
> return 0;
> }
>
> static int val = init();

I don't follow what you're code is supposed to be doing. 'val' always is
assigned 0. Is it's only purpose to cause the call to init()? Why would
you want to do that in this manner? It seems to me the solution you need
is as simple as:

      mythread *mythread_get() {
          mythread* t = *(current_thread.get());
          if (t == 0)
             current_thread.reset(new mythread *);
          return t;
      }

However, why thread_specific_ptr<mythread*>? My not just
thread_specific_ptr<mythread>? This code doesn't look valid to me, but
with out context I'm guessing.

> The problem is that I can't be sure, during init(), that current_thread
> has been constructed. I believe that's at the root of the bug I'm
> tracking.
>
> By contrast, in my pthread-specific code, I simply put the
> pthread_key_create() call at the start of init(), thus ensuring proper
> initialization order. But there's no analogous call I can make for a
> thread_specific_ptr -- that call is done during construction time.

pthread_key_create() only creates the key, it does not create any of the
thread specific storage for which there'd be an initialization order
issue. So, I don't understand what you're doing or what the problem is.

> So, what to do about it? Well, one obvious solution is to indirect
> current_thread:
>
> thread_specific_ptr<mythread*> *current_thread;
>
> then construct current_thread during init(). But that gives me yet one
> more indirection I have to do during mythread_get(). It's already slow
> as it is.
>
> Any suggestions?
>
>
> Which brings me to another source of slowness: because
> thread_specific_ptr automatically invokes delete on a thread's tss
> pointers when the thread goes away, I can't put a pointer to my real
> object, like this:
>
> thread_specific_ptr<mythread> current_thread;
>
> because mythread can't be deleted (for arcane reasons I won't get into
> here).

That depends. As long as you can set the value back to 0 before the
thread ends, you can still put this into thread_specific_ptr<>. Not a
universal solution, obviously, I just point it out in case it may help
with your current use case.

> It would be nice if there were a version of thread_specific_ptr
> which didn't delete, e.g.:
>
> thread_specific_ptr<mythread, non_deleting> current_thread;
>
> Just a suggestion...

Already in the thread_dev branch.

-- 
William E. Kempf

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk