Boost logo

Boost :

From: William E. Kempf (wekempf_at_[hidden])
Date: 2003-06-02 16:30:25


Chuck Messenger said:
> William E. Kempf wrote:
>> 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()?
>
> Yes.

OK, I've got some idea what you're doing now, but your comments still
aren't gelling.

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

Sorry slight bug here:

>> current_thread.reset(new mythread *);

{
   t = new mythread *;
   current_thread.reset(t);
}

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

I still don't understand. Since the mythread structure has an instance
per thread, you have to make a function call to get the current thread's
instance no matter what. That's what the above does. Nothing else is
done (well, there is a test and jump instruction, but do you need to
optimize even that out!?!) unless this is our first call. I don't see how
the init approach would be any more efficient, and would only work for the
main thread.

>> 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
>
> some_tss_value.reset(whatever);
>
> 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.

Ahh... gotcha. You want the thread_specific_ptr<> in the thread_dev branch.

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

No.

> static SomeType var1;
> static AnotherType var2 = var1.something();
>
> That is, is var1 guaranteed to be constructed before I initialize var2
> from it?

If they are in the same translation unit, yes. If not, no. With out
fully understanding how you're using this, this sounds dicey.

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

Doesn't sound standards conforming to me, but maybe I'm not understanding
what you're suggesting.

However, there are standards conforming ways to get what I believe you
want. In fact, what you're doing isn't really any different from what I
do in the thread implementation in the thread_dev branch. Maybe you
should look there for inspiration. If that doesn't help, let me know and
I'll see if I can't do better for you.

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