
I agree, and it should be able to clean up non-boost threads as well - consider what happens if you're writing a library, and not a program - you then have no control over who creates threads or how they do so. I believe it would be unacceptable to say "you can only use this library if you also use Boost.Threads"; in such cases thread_specific_ptr is exceptionally useful IMO.
While having heard this argument quite often, I still do not understand how this can ever work (in a reliable way).
Say you have a peace of code located in module A that is starting a thread by whatever means (System thread e.g.).
Now in your module B you have a (global) TSS variable. A calls into B. When should the TSS be initialized? On first use? I am afraid that is not trivially possible, since you (as far as I understand on WIndows) will need to acquire a slot for this variable when the process starts up (normally in DLL_PROCESS_ATTACH). You might argue that you can have a global object in B whose constructor can handle this. Ok this would work. You can acquire the Slot during initialization, and can acquire your data on the heap on first use.
_But_ what is about c-runtime initialisation? Perhaps I am a little bit to paranoid about this but the per thread data holds items like
unsigned long _tdoserrno; /* _doserrno value */ unsigned int _fpds; /* Floating Point data segment */ unsigned long _holdrand; /* rand() seed value */ char * _token; /* ptr to strtok() token */
to cite only a few, that are clearly related to a couple of runtime lib functions.
How can you ever be sure the c-runtime will behave correctly when these are not available/initialized for your thread (note you did never call _beginthread!).
I agree violently that the calling thread must have been started with __beginthread. I can't think of any threading lib where this is not the case - even exception handling doesn't work in a thread unless it was created with __beginthread. This is very different however from requiring that the thread was created with Boost.Threads, which is what was being suggested. As for C runtime initialisation, I believe that this is a non-issue: the slot is allocated (TlsAlloc) when the lib is loaded, but no C runtime calls are made at this point. Calls to the C runtime are only made when the slot is first *accessed* at which point the object gets created with a call to new, if it does not already exist. When it comes to cleanup we may have a problem if the exe is statically linked, but if it's dynamically linked then Boost.Threads cleanup *will* get called before that of the runtime on which it depends. I need to think some more about statically linked executables... John.