Boost logo

Boost :

From: Chuck Messenger (chuckm_at_[hidden])
Date: 2003-06-02 14:39:00

William E. Kempf wrote:
> 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.

Background: I have a structure of information, 'mythread', of which I
need one per thread. That is, I've grouped all my tss variables into a
single structure. I need to "bootstrap" the main thread. Hence the
static variable initialization -- my thought (perhaps incorrect) being
that 'val' will be initialized before main() begins, thus bootstrapping
the main thread. I believe that's right -- that all static variables in
all translation units are initialized before main()...?

(The point is that I don't have control of main() -- otherwise, I could
initialize current_thread in main(). This code is part of a library.)

> '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;
> }

I was, perhaps misguidedly, trying to avoid the need to call a function
-- since I access the mythread structure alot. Ideally, I want as much
speed as the underlying OS-level implementation will allow.

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

Because I don't want the 'mythread' structure to get deleted when the
thread dies. My understanding of tss is that part of the semantics is
that, if you do


then when the thread ends, the thread library does 'delete whatever'.
Therefore, I'm forced to have tss store a pointer to mystruct*, rather
than mystruct* itself.

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

The problem is that it is necessary for pthread_key_create() to be
called before I can set a value for it. Can I be sure that
thread_specific_ptr<mythread*> has been initialized before I try using
it during init()? I'm not that clear on C++ initialization order
semantics for statics. If I do:

     extern int i;
     extern int j;
     int j = i;
     int i = j;

then what happens? It isn't obvious to me how the order would be
established. And so, can I assume that the following is guaranteed to work?

     static SomeType var1;
     static AnotherType var2 = var1.something();

That is, is var1 guaranteed to be constructed before I initialize var2
from it?

The thing is: there is some sort of bug with (Boost Threads) TSS -- the
way I'm using it, that is. My attempts at tracking the bug failed, so I
resorted to replacing TSS with native pthreads, and that worked. The
only difference that I could glean between the TSS and pthreads versions
of my code were in init(). If I spent some more time on it, perhaps I
could definitively nail down this suspicion.

So, as it is, I *suspect* that the problem is that "accessing a static
thread_specific_ptr<> during initialization of another static variable"
isn't guaranteed to work (because C++ doesn't, perhaps, define
initialization order for statics, so the thread_specific_ptr<> object
won't necessarily have been created by the time it is used).

Assuming this is correct, then I'm proposing a new force_construction()
method for thread_specific_ptr<>, to ameliorate this kind of problem.
During thread_specific_ptr<>'s normal construction, it would detect
whether it had been "pre-constructed".

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

OK -- that's a possibility. Thanks.

     - Chuck Messenger

Boost list run by bdawes at, gregod at, cpdaniel at, john at