The different configurations you see are related to #[thread_local]
, a feature that is intended to replace the thread_local!
macro to make the user code more straightforward, e.g.:
#![feature(thread_local)]
#[thread_local]
pub static mut VAR: u64 = 42;
However, at the moment of writing, this feature is not fully implemented yet (you can find the tracking issue here). It is used internally in the compiler code though, and that is the magic you see in the actual 'fast' implementation in std::thread::LocalKey
:
#[thread_local]
#[cfg(all(
target_thread_local,
not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
))]
static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
$crate::thread::__FastLocalKeyInner::new();
Notice the #[thread_local]
attribute at the top. It is then translated down to LLVM IR, so the actual implementation of TLS (thread-local storage) is carried by LLVM and implements the ELF TLS models. This is the default configuration.
how do I choose which one to use?
You'll need to compile your own rustc
version with the target_thread_local
feature omitted. In that case, the os
variant of std::thread::LocalKey
will be used, and then, depending on a platform, it can use pthreads (Unix), or Windows API, or something else.
WebAssembly is a special case: as it doesn't support threads, TLS will be translated down to simple static variables.
LocalKey
? It states: This key uses the fastest possible implementation available to it for the target platform and Initialization is dynamically performed on the first call to with within a thread, and values that implement Drop get destructed when a thread exits which appear to answer both of your questions. – Akira