#![unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")] #![cfg_attr(test, allow(unused))] // There are three thread-local implementations: "static", "fast", "OS". // The "OS" thread local key type is accessed via platform-specific API calls and is slow, while the // "fast" key type is accessed via code generated via LLVM, where TLS keys are set up by the linker. // "static" is for single-threaded platforms where a global static is sufficient. cfg_if::cfg_if! { if #[cfg(any(all(target_family = "wasm", not(target_feature = "atomics")), target_os = "uefi"))] { #[doc(hidden)] mod static_local; #[doc(hidden)] pub use static_local::{EagerStorage, LazyStorage, thread_local_inner}; } else if #[cfg(target_thread_local)] { #[doc(hidden)] mod fast_local; #[doc(hidden)] pub use fast_local::{EagerStorage, LazyStorage, thread_local_inner}; } else { #[doc(hidden)] mod os_local; #[doc(hidden)] pub use os_local::{Key, thread_local_inner}; } } /// Run a callback in a scenario which must not unwind (such as a `extern "C" /// fn` declared in a user crate). If the callback unwinds anyway, then /// `rtabort` with a message about thread local panicking on drop. #[inline] #[allow(dead_code)] fn abort_on_dtor_unwind(f: impl FnOnce()) { // Using a guard like this is lower cost. let guard = DtorUnwindGuard; f(); core::mem::forget(guard); struct DtorUnwindGuard; impl Drop for DtorUnwindGuard { #[inline] fn drop(&mut self) { // This is not terribly descriptive, but it doesn't need to be as we'll // already have printed a panic message at this point. rtabort!("thread local panicked on drop"); } } }