Afaik a (static) thread local variable is destroyed (immediately ?) when the associated thread terminates.
Does the standard mandates that the destruction happens on computing time of the dying thread? In other words, is the thread id inside of such an destructor the tid of the associated thread and thread_local variables are gone before final death of the thread?
While writing this, I ask myself if even construction of thread_local objects are always mandatory happen via the associated thread?
[basic.start.dynamic]/7 It is implementation-defined whether the dynamic initialization of a non-block non-inline variable with thread storage duration is sequenced before the first statement of the initial function of a thread or is deferred. If it is deferred, the initialization associated with the entity for thread t is sequenced before the first non-initialization odr-use by t of any non-inline variable with thread storage duration defined in the same translation unit as the variable to be initialized.
Now, "sequenced before" is defined ([intro.execution]/8) as "an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread". Emphasis mine. I think this implies that the initialization must be performed by the same thread as the initial function, or else one can't be sequenced before the other.
There isn't a similar "sequenced before" wording for thread termination. The standard only says that thread-local objects are destroyed "as a result of" thread termination, whatever that means:
[basic.start.term]/2 Constructed objects with thread storage duration within a given thread are destroyed as a result of returning from the initial function of that thread and as a result of that thread calling
std::exit
.
The standard does say that the destruction of several thread-local objects is sequenced relative to each other; so at least, all such objects must be destroyed on the same thread:
[basic.start.term]/3 ... If the completion of the constructor or dynamic initialization of an object with thread storage duration is sequenced before that of another, the completion of the destructor of the second is sequenced before the initiation of the destructor of the first...
I think the intent is that thread-local objects are destroyed by the same thread that initialized them; and it's hard to imagine an implementation doing anything else.