Re: [boost] Re: Re: Re: Thread-Local Storage (TLS) and templates

2003-02-25 Thread William E. Kempf

Edward Diener said:
> William E. Kempf wrote:
>>> You can clean up your own TLS index ( or indices ) in your DllMain
>>> routine when the seond parameter is DLL_PROCESS_DETACH, meaning that
>>> your process is being exited. AFAIK this is the standard way to do
>>> this.
>>
>> (Note: The issue is more with cleaning up TLS data then with cleaning
>> up TLS indices/slots.  So we're really talking about
>> DLL_THREAD_DETACH here.)
>
> Then perhaps the weakness is not really with TLS on Windows but rather
> with limitations to actions one can perform at DLL_THREAD_DETACH time.

No, the issue is that the only mechanism provided for TLS cleanup is to
hook DllMain, or to explicitly clean up the data in the thread before it
exits.  The former is unusable in several cases, while the latter can only
be done if you control the creation of the thread.

> Would you describe these issues specifically ?

I did, below.

>> This is the MS way, not the "standard" way.
>
> "This" referring to what above ?

Using DllMain to cleanup TLS data.

>>  And it's full of issues.
>> You are quite limited in what you can safely do within DllMain.  Any
>> calls to synchronization routines is likely to deadlock the entire
>> process.
>
> I agree that this is so. You can't sit and wait until some other thread
> has done something, via a Windows synchronization primitive, when you
> are processing DLL_THREAD_DETACH. What is the situation where this is
> necessary ?

There are numerous situations where this is necessary.  For example, the
cleanup mechanism in both Boost.Threads and pthreads-win32 use mutexes,
which can potentially cause *process* deadlock.  If the TLS data is shared
across threads, or references data shared across threads, or simply calls
a routine that does synchronization in the cleanup, all of which are not
that uncommon, and some of which are hard for the programmer to avoid (do
you know what routines do synchronization internally?), you risk deadlock.

>>  As is calling any routines that load/unload a DLL.
>
> The workaround is not to dynamically load/unload a DLL as part of thread
> processing.

Do you know what routines do this as part of their implementation?  To
quote the MSDN "Calling imported functions other than those located in
Kernel32.dll may result in problems that are difficult to diagnose."  And
since a very large number of Win32 API functions are imported... I think
you see the issue.

> Yes, it is cleaner to do so when one only needs a DLL for a
> specific time but the overhead of statically linking a DLL into a
> process instead is minimal, although I agree that dynamic loading is
> often a cleaner design. I do agree with you that the inability to
> dynamically load and unload a DLL at DLL_THREAD_ATTACH/DLL_THREAD_DETACH
> is an unfortunate imposition and that this is poor design on MS's part.
> I am still not clear whay this is so and why this limitation exists on
> Windows.

I honestly don't care.  The only time I've ever found this design to be
unusable is when dealing specifically with the cleanup of TLS data, which
would be much better implemented as a registered cleanup routine in the
first place.  Fix this, and I don't care about this artifact of the DLL
system on Win32 platforms.

>>  There's
>> also the issue of forcing the use of a DLL with this scheme, which
>> many users rightfully dislike (this is why there are so many thread
>> creation routines on Windows).
>
> I could be mistaken but I believe that TLS works just as effectively in
> static LIBs as it does with DLLs. The difference is that one must do
> manual initialization routines and finalization routines of TLS data for
> different threads, as opposed to what one may do automatically using
> DLL_THREAD_ATTACH/DLL_THREAD_DETACH. But certainly one is not forced to
> use only DLLs or only static LIBs if the implementation supports both.

Initialization isn't really an issue, as you can do lazy initialization
(synchronization issues aside, as they are solvable).  It's the
finalization that's an issue, and it's resulted in the numerous thread
creation routines and the rules for when to use which one.  If you call
any C RTL routines (which may allocate TLS) you can't call CreateThread,
but must instead call _beginthread(ex).  Likewise, if you call any MFC
routines you can't call CreateThread or _beginthread(ex) but instead must
call AfxBeginThread, lest you leak TLS data allocated by these routines. 
This is an issue for Boost.Threads, which has it's own thread creation
routines, because I don't know how a user will use the thread.  It's a
problem for other libraries if they have thread creation routines, or have
user registered callbacks executed by the threads created by the library. 
It's a problem if you want to make use of the built in Win32 thread
pooling mechanisms, since those threads will be created using
CreateThread.  And so on.

 I won't be as critical as Alexander, but I will agree that the MS
 TLS implementation has s

[boost] Re: Re: Re: Thread-Local Storage (TLS) and templates

2003-02-24 Thread Edward Diener
William E. Kempf wrote:
> Edward Diener said:
>> "William E. Kempf" <[EMAIL PROTECTED]> wrote in message
>> news:[EMAIL PROTECTED]
>>>
>>> Edward Diener said:
 "Alexander Terekhov" <[EMAIL PROTECTED]> wrote in message
 news:[EMAIL PROTECTED]
>
> Ken Hagan wrote:
>>
>> Alexander Terekhov wrote:
>>>
>>> I, for one, believe strongly that "&k" is nothing but
>>>
>>> "static_cast(pthread_getspecific(__k_key));"
>>>
>>> It *isn't* a compile-time constant (just like &errno isn't a
>>> compile time constant).
>>
>> MSVC has no pthread_getspecific(), so I venture to suggest that
>>> your
> belief probably isn't valid for that compiler.
>
> Uhmm. In return, I venture to suggest that MS-TLS can and shall be
>>> characterized as ``utterly busted.''
>
> "If a DLL declares any nonlocal data or object as
>  __declspec(thread), it can cause a protection fault if
> dynamically loaded."

 This is well-known by many and has never been hidden by MS. It
>>> doesn't mean __declspec(thread) is busted, it just means that it is
>>> limited to only those cases in which the DLL is not dynamically
>>> loaded, which is the vast majority of cases. Of course to make TLS
>>> completely foolproof, one does not use __declspec(thread) but
>>> instead one uses the Win32 TLS API functions instead.
>>>
>>> Where you run into issues with TLS cleanup ;).
>>
>> Such as ?
>>
>> You can clean up your own TLS index ( or indices ) in your DllMain
>> routine when the seond parameter is DLL_PROCESS_DETACH, meaning that
>> your process is being exited. AFAIK this is the standard way to do
>> this.
>
> (Note: The issue is more with cleaning up TLS data then with cleaning
> up TLS indices/slots.  So we're really talking about
> DLL_THREAD_DETACH here.)

Then perhaps the weakness is not really with TLS on Windows but rather with
limitations to actions one can perform at DLL_THREAD_DETACH time. Would you
describe these issues specifically ?

>
> This is the MS way, not the "standard" way.

"This" referring to what above ?

>  And it's full of issues.
> You are quite limited in what you can safely do within DllMain.  Any
> calls to synchronization routines is likely to deadlock the entire
> process.

I agree that this is so. You can't sit and wait until some other thread has
done something, via a Windows synchronization primitive, when you are
processing DLL_THREAD_DETACH. What is the situation where this is necessary
?

>  As is calling any routines that load/unload a DLL.

The workaround is not to dynamically load/unload a DLL as part of thread
processing. Yes, it is cleaner to do so when one only needs a DLL for a
specific time but the overhead of statically linking a DLL into a process
instead is minimal, although I agree that dynamic loading is often a cleaner
design. I do agree with you that the inability to dynamically load and
unload a DLL at DLL_THREAD_ATTACH/DLL_THREAD_DETACH is an unfortunate
imposition and that this is poor design on MS's part. I am still not clear
whay this is so and why this limitation exists on Windows.

>  There's
> also the issue of forcing the use of a DLL with this scheme, which
> many users rightfully dislike (this is why there are so many thread
> creation routines on Windows).

I could be mistaken but I believe that TLS works just as effectively in
static LIBs as it does with DLLs. The difference is that one must do manual
initialization routines and finalization routines of TLS data for different
threads, as opposed to what one may do automatically using
DLL_THREAD_ATTACH/DLL_THREAD_DETACH. But certainly one is not forced to use
only DLLs or only static LIBs if the implementation supports both.

>
>>> I won't be as critical as Alexander, but I will agree that the MS
>>> TLS implementation has serious design issues which need to be
>>> corrected.
>>
>> OK, this isn't the place to debate Windows TLS, but I have not run
>> into such design issues myself.
>
> You have, you just weren't necessarily aware of it ;).

No, I haven't for what I was doing  but that doesn't mean you or others
haven't. It seems that the problems are MS's design of what one can do in
DLL_THREAD_ATTACH/DLL_THREAD_DETACH itself instead of in TLS. If you can
point out specific problems in Boost.Threads I would be glad to hear about
it.

>  Again, I
> point you to the various thread creation routines as the number one
> issue that we've all encountered.  If you've needed to do complex
> cleanup, or wanted to not have to deal with a DLL, then you've run
> into the other problems more directly.  This has been the biggest
> issue with implementating thread_specific_ptr<> for me, and what we
> have today is quite ugly and fragile.
>
> And I do think it's a proper place to debate Windows TLS.  It directly
> effects Boost.Threads, and the more people we make aware of the
> problems, the more likely something will be done about it.



___