Boost logo

Boost :

From: Ken Hagan (K.Hagan_at_[hidden])
Date: 2003-02-20 05:00:22


Reading various replies, we appear to have a couple of things that
aren't completely pinned down: the type of "&k" and the implementation
of TLS.

 1 If "&k" is a regular pointer to integer and TLS is implemented by
   tweaking page tables for each thread, then "&k" has the same value
   in each thread and C<&k> is the same type, but any member of C<&K>
   that uses its template parameter will behave differently from one
   thread to another.

   Is this a problem. I don't think so. Consider...

      __declspec(thread) k
      int foo() { return k; }

   We can easily write a template, C, and instantiate it "C<&k>" and
   have its behaviour vary per-thread, although the value of the
   template parameter is the same.

   With this TLS implementation, we can't expose TLS data to another
   thread except by copying it. The workaround is simply to store a
   pointer to the actual data or object.

 2 If "&k" is a regular pointer and TLS is implemented by allocating
   separate blocks for each thread and storing the addresses in a
   register, then "&k" has a different value in each thread and is no
   longer a compile time constant so you can't write the template.

 3 If "&k" is a special pointer, then we can implement TLS either way,
   but we must define a conversion between special and regular pointers.
   For ordinary functions expecting "int*" the compiler simply invokes
   this conversion when passing the argument and no-one gets upset.
   However, for the template case, that conversion is a run-time
   operation so it clearly can't apply.

3a If we allow C<&k>, then "&k" is the offset into the TLS table, the
   instantiated code includes the conversion, and C<&k> is the same
   type in every thread because the offset is the same. It is then
   possible to initialise static variables with the converted value
   of "&k" and the results depend on the thread that ran first. Again,
   we have the same "problem" passing a pointer to a function, so I'm
   not bothered by this.

   Alternatively, we could insist that template authors explicitly
   declare their template parameter to be "int __thread*", but I don't
   see that this buys us anything. On the contrary, it makes explicit
   a whole new kind of pointer.

   Alternatively, we could just ban the template instantiation, forcing
   users to write the helper function "foo()" and instantiate on that.
   Again, I don't think this buys us anything.

I think 3a describes the "existing practice" of MSVC and is the solution
that offers the greatest flexibility, allowing templates to be written
naturally and TLS data to be shared between threads if that's really
what you want to do.


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