[boost] Re: thread lib: thread specific storage problem

2003-06-03 Thread Chuck Messenger
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_ptrmythread* 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()? 
Yes.

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_ptrmythread*?  My not just
thread_specific_ptrmythread?  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.


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

[boost] Re: thread lib: thread specific storage problem

2003-06-03 Thread Chuck Messenger
Chuck Messenger wrote:
  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?
Referring to TC++PL 3rd ed, I see that, indeed, statics are initialized 
in the order declared.

So, my suggestion to fix the non-problem doesn't make sense (besides 
which, the proposed solution was unsound).  I'll have to (some day!) try 
to nail down the TSS-related bug -- perhaps it's a bug in the Boost 
Threads lib...

- Chuck

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: thread lib: thread specific storage problem

2003-06-03 Thread William E. Kempf

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_ptrmythread*?  My not just
 thread_specific_ptrmythread?  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_ptrmythread* 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