1 //! Thread local storage
3 #![unstable(feature = "thread_local_internals", issue = "none")]
5 #[cfg(all(test, not(target_os = "emscripten")))]
11 use crate::cell::{Cell, RefCell};
12 use crate::error::Error;
15 /// A thread local storage key which owns its contents.
17 /// This key uses the fastest possible implementation available to it for the
18 /// target platform. It is instantiated with the [`thread_local!`] macro and the
19 /// primary method is the [`with`] method.
21 /// The [`with`] method yields a reference to the contained value which cannot be
22 /// sent across threads or escape the given closure.
24 /// # Initialization and Destruction
26 /// Initialization is dynamically performed on the first call to [`with`]
27 /// within a thread, and values that implement [`Drop`] get destructed when a
28 /// thread exits. Some caveats apply, which are explained below.
30 /// A `LocalKey`'s initializer cannot recursively depend on itself, and using
31 /// a `LocalKey` in this way will cause the initializer to infinitely recurse
32 /// on the first call to `with`.
37 /// use std::cell::RefCell;
40 /// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
43 /// assert_eq!(*f.borrow(), 1);
44 /// *f.borrow_mut() = 2;
47 /// // each thread starts out with the initial value of 1
48 /// let t = thread::spawn(move|| {
50 /// assert_eq!(*f.borrow(), 1);
51 /// *f.borrow_mut() = 3;
55 /// // wait for the thread to complete and bail out on panic
56 /// t.join().unwrap();
58 /// // we retain our original value of 2 despite the child thread
60 /// assert_eq!(*f.borrow(), 2);
64 /// # Platform-specific behavior
66 /// Note that a "best effort" is made to ensure that destructors for types
67 /// stored in thread local storage are run, but not all platforms can guarantee
68 /// that destructors will be run for all types in thread local storage. For
69 /// example, there are a number of known caveats where destructors are not run:
71 /// 1. On Unix systems when pthread-based TLS is being used, destructors will
72 /// not be run for TLS values on the main thread when it exits. Note that the
73 /// application will exit immediately after the main thread exits as well.
74 /// 2. On all platforms it's possible for TLS to re-initialize other TLS slots
75 /// during destruction. Some platforms ensure that this cannot happen
76 /// infinitely by preventing re-initialization of any slot that has been
77 /// destroyed, but not all platforms have this guard. Those platforms that do
78 /// not guard typically have a synthetic limit after which point no more
79 /// destructors are run.
80 /// 3. When the process exits on Windows systems, TLS destructors may only be
81 /// run on the thread that causes the process to exit. This is because the
82 /// other threads may be forcibly terminated.
84 /// ## Synchronization in thread-local destructors
86 /// On Windows, synchronization operations (such as [`JoinHandle::join`]) in
87 /// thread local destructors are prone to deadlocks and so should be avoided.
88 /// This is because the [loader lock] is held while a destructor is run. The
89 /// lock is acquired whenever a thread starts or exits or when a DLL is loaded
90 /// or unloaded. Therefore these events are blocked for as long as a thread
91 /// local destructor is running.
93 /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
94 /// [`JoinHandle::join`]: crate::thread::JoinHandle::join
95 /// [`with`]: LocalKey::with
96 #[stable(feature = "rust1", since = "1.0.0")]
97 pub struct LocalKey<T: 'static> {
98 // This outer `LocalKey<T>` type is what's going to be stored in statics,
99 // but actual data inside will sometimes be tagged with #[thread_local].
100 // It's not valid for a true static to reference a #[thread_local] static,
101 // so we get around that by exposing an accessor through a layer of function
102 // indirection (this thunk).
104 // Note that the thunk is itself unsafe because the returned lifetime of the
105 // slot where data lives, `'static`, is not actually valid. The lifetime
106 // here is actually slightly shorter than the currently running thread!
108 // Although this is an extra layer of indirection, it should in theory be
109 // trivially devirtualizable by LLVM because the value of `inner` never
110 // changes and the constant should be readonly within a crate. This mainly
111 // only runs into problems when TLS statics are exported across crates.
112 inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>,
115 #[stable(feature = "std_debug", since = "1.16.0")]
116 impl<T: 'static> fmt::Debug for LocalKey<T> {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.debug_struct("LocalKey").finish_non_exhaustive()
122 /// Declare a new thread local storage key of type [`std::thread::LocalKey`].
126 /// The macro wraps any number of static declarations and makes them thread local.
127 /// Publicity and attributes for each static are allowed. Example:
130 /// use std::cell::RefCell;
132 /// pub static FOO: RefCell<u32> = RefCell::new(1);
135 /// static BAR: RefCell<f32> = RefCell::new(1.0);
140 /// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
143 /// [`std::thread::LocalKey`]: crate::thread::LocalKey
145 #[stable(feature = "rust1", since = "1.0.0")]
146 #[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")]
147 #[allow_internal_unstable(thread_local_internals)]
148 macro_rules! thread_local {
149 // empty (base case for the recursion)
152 ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => (
153 $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
154 $crate::thread_local!($($rest)*);
157 ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => (
158 $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
161 // process multiple declarations
162 ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
163 $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
164 $crate::thread_local!($($rest)*);
167 // handle a single declaration
168 ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
169 $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
174 #[unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")]
176 #[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
177 #[allow_internal_unsafe]
178 macro_rules! __thread_local_inner {
179 // used to generate the `LocalKey` value for const-initialized thread locals
180 (@key $t:ty, const $init:expr) => {{
181 #[cfg_attr(not(windows), inline)] // see comments below
182 #[deny(unsafe_op_in_unsafe_fn)]
184 _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
185 ) -> $crate::option::Option<&'static $t> {
186 const INIT_EXPR: $t = $init;
188 // wasm without atomics maps directly to `static mut`, and dtors
189 // aren't implemented because thread dtors aren't really a thing
192 // FIXME(#84224) this should come after the `target_thread_local`
194 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
196 static mut VAL: $t = INIT_EXPR;
197 unsafe { $crate::option::Option::Some(&VAL) }
200 // If the platform has support for `#[thread_local]`, use it.
203 not(all(target_family = "wasm", not(target_feature = "atomics"))),
207 static mut VAL: $t = INIT_EXPR;
209 // If a dtor isn't needed we can do something "very raw" and
211 if !$crate::mem::needs_drop::<$t>() {
213 return $crate::option::Option::Some(&VAL)
217 // 0 == dtor not registered
218 // 1 == dtor registered, dtor not run
219 // 2 == dtor registered and is running or has run
221 static mut STATE: $crate::primitive::u8 = 0;
223 unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) {
224 let ptr = ptr as *mut $t;
227 $crate::debug_assert_eq!(STATE, 1);
229 $crate::ptr::drop_in_place(ptr);
235 // 0 == we haven't registered a destructor, so do
238 $crate::thread::__FastLocalKeyInner::<$t>::register_dtor(
239 $crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8,
243 $crate::option::Option::Some(&VAL)
245 // 1 == the destructor is registered and the value
246 // is valid, so return the pointer.
247 1 => $crate::option::Option::Some(&VAL),
248 // otherwise the destructor has already run, so we
249 // can't give access.
250 _ => $crate::option::Option::None,
255 // On platforms without `#[thread_local]` we fall back to the
256 // same implementation as below for os thread locals.
258 not(target_thread_local),
259 not(all(target_family = "wasm", not(target_feature = "atomics"))),
263 const fn __init() -> $t { INIT_EXPR }
264 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
265 $crate::thread::__OsLocalKeyInner::new();
266 #[allow(unused_unsafe)]
269 if let $crate::option::Option::Some(init) = _init {
270 if let $crate::option::Option::Some(value) = init.take() {
272 } else if $crate::cfg!(debug_assertions) {
273 $crate::unreachable!("missing initial value");
283 $crate::thread::LocalKey::new(__getit)
287 // used to generate the `LocalKey` value for `thread_local!`
288 (@key $t:ty, $init:expr) => {
291 fn __init() -> $t { $init }
293 // When reading this function you might ask "why is this inlined
294 // everywhere other than Windows?", and that's a very reasonable
295 // question to ask. The short story is that it segfaults rustc if
296 // this function is inlined. The longer story is that Windows looks
297 // to not support `extern` references to thread locals across DLL
298 // boundaries. This appears to at least not be supported in the ABI
299 // that LLVM implements.
301 // Because of this we never inline on Windows, but we do inline on
302 // other platforms (where external references to thread locals
303 // across DLLs are supported). A better fix for this would be to
304 // inline this function on Windows, but only for "statically linked"
305 // components. For example if two separately compiled rlibs end up
306 // getting linked into a DLL then it's fine to inline this function
307 // across that boundary. It's only not fine to inline this function
308 // across a DLL boundary. Unfortunately rustc doesn't currently
309 // have this sort of logic available in an attribute, and it's not
310 // clear that rustc is even equipped to answer this (it's more of a
311 // Cargo question kinda). This means that, unfortunately, Windows
312 // gets the pessimistic path for now where it's never inlined.
314 // The issue of "should enable on Windows sometimes" is #84933
315 #[cfg_attr(not(windows), inline)]
317 init: $crate::option::Option<&mut $crate::option::Option<$t>>,
318 ) -> $crate::option::Option<&'static $t> {
319 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
320 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
321 $crate::thread::__StaticLocalKeyInner::new();
326 not(all(target_family = "wasm", not(target_feature = "atomics"))),
328 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
329 $crate::thread::__FastLocalKeyInner::new();
332 not(target_thread_local),
333 not(all(target_family = "wasm", not(target_feature = "atomics"))),
335 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
336 $crate::thread::__OsLocalKeyInner::new();
338 // FIXME: remove the #[allow(...)] marker when macros don't
339 // raise warning for missing/extraneous unsafe blocks anymore.
340 // See https://github.com/rust-lang/rust/issues/74838.
341 #[allow(unused_unsafe)]
344 if let $crate::option::Option::Some(init) = init {
345 if let $crate::option::Option::Some(value) = init.take() {
347 } else if $crate::cfg!(debug_assertions) {
348 $crate::unreachable!("missing default value");
357 $crate::thread::LocalKey::new(__getit)
361 ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
362 $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
363 $crate::__thread_local_inner!(@key $t, $($init)*);
367 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
368 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
370 #[derive(Clone, Copy, Eq, PartialEq)]
371 pub struct AccessError;
373 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
374 impl fmt::Debug for AccessError {
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376 f.debug_struct("AccessError").finish()
380 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
381 impl fmt::Display for AccessError {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 fmt::Display::fmt("already destroyed", f)
387 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
388 impl Error for AccessError {}
390 impl<T: 'static> LocalKey<T> {
393 feature = "thread_local_internals",
394 reason = "recently added to create a key",
397 #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
398 pub const unsafe fn new(
399 inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>,
404 /// Acquires a reference to the value in this TLS key.
406 /// This will lazily initialize the value if this thread has not referenced
411 /// This function will `panic!()` if the key currently has its
412 /// destructor running, and it **may** panic if the destructor has
413 /// previously been run for this thread.
414 #[stable(feature = "rust1", since = "1.0.0")]
415 pub fn with<F, R>(&'static self, f: F) -> R
419 self.try_with(f).expect(
420 "cannot access a Thread Local Storage value \
421 during or after destruction",
425 /// Acquires a reference to the value in this TLS key.
427 /// This will lazily initialize the value if this thread has not referenced
428 /// this key yet. If the key has been destroyed (which may happen if this is called
429 /// in a destructor), this function will return an [`AccessError`].
433 /// This function will still `panic!()` if the key is uninitialized and the
434 /// key's initializer panics.
435 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
437 pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
442 let thread_local = (self.inner)(None).ok_or(AccessError)?;
447 /// Acquires a reference to the value in this TLS key, initializing it with
448 /// `init` if it wasn't already initialized on this thread.
450 /// If `init` was used to initialize the thread local variable, `None` is
451 /// passed as the first argument to `f`. If it was already initialized,
452 /// `Some(init)` is passed to `f`.
456 /// This function will panic if the key currently has its destructor
457 /// running, and it **may** panic if the destructor has previously been run
459 fn initialize_with<F, R>(&'static self, init: T, f: F) -> R
461 F: FnOnce(Option<T>, &T) -> R,
464 let mut init = Some(init);
465 let reference = (self.inner)(Some(&mut init)).expect(
466 "cannot access a Thread Local Storage value \
467 during or after destruction",
474 impl<T: 'static> LocalKey<Cell<T>> {
475 /// Sets or initializes the contained value.
477 /// Unlike the other methods, this will *not* run the lazy initializer of
478 /// the thread local. Instead, it will be directly initialized with the
479 /// given value if it wasn't initialized yet.
483 /// Panics if the key currently has its destructor running,
484 /// and it **may** panic if the destructor has previously been run for this thread.
489 /// #![feature(local_key_cell_methods)]
490 /// use std::cell::Cell;
493 /// static X: Cell<i32> = panic!("!");
496 /// // Calling X.get() here would result in a panic.
498 /// X.set(123); // But X.set() is fine, as it skips the initializer above.
500 /// assert_eq!(X.get(), 123);
502 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
503 pub fn set(&'static self, value: T) {
504 self.initialize_with(Cell::new(value), |value, cell| {
505 if let Some(value) = value {
506 // The cell was already initialized, so `value` wasn't used to
507 // initialize it. So we overwrite the current value with the
509 cell.set(value.into_inner());
514 /// Returns a copy of the contained value.
516 /// This will lazily initialize the value if this thread has not referenced
521 /// Panics if the key currently has its destructor running,
522 /// and it **may** panic if the destructor has previously been run for this thread.
527 /// #![feature(local_key_cell_methods)]
528 /// use std::cell::Cell;
531 /// static X: Cell<i32> = Cell::new(1);
534 /// assert_eq!(X.get(), 1);
536 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
537 pub fn get(&'static self) -> T
541 self.with(|cell| cell.get())
544 /// Takes the contained value, leaving `Default::default()` in its place.
546 /// This will lazily initialize the value if this thread has not referenced
551 /// Panics if the key currently has its destructor running,
552 /// and it **may** panic if the destructor has previously been run for this thread.
557 /// #![feature(local_key_cell_methods)]
558 /// use std::cell::Cell;
561 /// static X: Cell<Option<i32>> = Cell::new(Some(1));
564 /// assert_eq!(X.take(), Some(1));
565 /// assert_eq!(X.take(), None);
567 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
568 pub fn take(&'static self) -> T
572 self.with(|cell| cell.take())
575 /// Replaces the contained value, returning the old value.
577 /// This will lazily initialize the value if this thread has not referenced
582 /// Panics if the key currently has its destructor running,
583 /// and it **may** panic if the destructor has previously been run for this thread.
588 /// #![feature(local_key_cell_methods)]
589 /// use std::cell::Cell;
592 /// static X: Cell<i32> = Cell::new(1);
595 /// assert_eq!(X.replace(2), 1);
596 /// assert_eq!(X.replace(3), 2);
598 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
599 pub fn replace(&'static self, value: T) -> T {
600 self.with(|cell| cell.replace(value))
604 impl<T: 'static> LocalKey<RefCell<T>> {
605 /// Acquires a reference to the contained value.
607 /// This will lazily initialize the value if this thread has not referenced
612 /// Panics if the value is currently mutably borrowed.
614 /// Panics if the key currently has its destructor running,
615 /// and it **may** panic if the destructor has previously been run for this thread.
620 /// #![feature(local_key_cell_methods)]
621 /// use std::cell::RefCell;
624 /// static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
627 /// X.with_borrow(|v| assert!(v.is_empty()));
629 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
630 pub fn with_borrow<F, R>(&'static self, f: F) -> R
634 self.with(|cell| f(&cell.borrow()))
637 /// Acquires a mutable reference to the contained value.
639 /// This will lazily initialize the value if this thread has not referenced
644 /// Panics if the value is currently borrowed.
646 /// Panics if the key currently has its destructor running,
647 /// and it **may** panic if the destructor has previously been run for this thread.
652 /// #![feature(local_key_cell_methods)]
653 /// use std::cell::RefCell;
656 /// static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
659 /// X.with_borrow_mut(|v| v.push(1));
661 /// X.with_borrow(|v| assert_eq!(*v, vec![1]));
663 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
664 pub fn with_borrow_mut<F, R>(&'static self, f: F) -> R
666 F: FnOnce(&mut T) -> R,
668 self.with(|cell| f(&mut cell.borrow_mut()))
671 /// Sets or initializes the contained value.
673 /// Unlike the other methods, this will *not* run the lazy initializer of
674 /// the thread local. Instead, it will be directly initialized with the
675 /// given value if it wasn't initialized yet.
679 /// Panics if the value is currently borrowed.
681 /// Panics if the key currently has its destructor running,
682 /// and it **may** panic if the destructor has previously been run for this thread.
687 /// #![feature(local_key_cell_methods)]
688 /// use std::cell::RefCell;
691 /// static X: RefCell<Vec<i32>> = panic!("!");
694 /// // Calling X.with() here would result in a panic.
696 /// X.set(vec![1, 2, 3]); // But X.set() is fine, as it skips the initializer above.
698 /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
700 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
701 pub fn set(&'static self, value: T) {
702 self.initialize_with(RefCell::new(value), |value, cell| {
703 if let Some(value) = value {
704 // The cell was already initialized, so `value` wasn't used to
705 // initialize it. So we overwrite the current value with the
707 *cell.borrow_mut() = value.into_inner();
712 /// Takes the contained value, leaving `Default::default()` in its place.
714 /// This will lazily initialize the value if this thread has not referenced
719 /// Panics if the value is currently borrowed.
721 /// Panics if the key currently has its destructor running,
722 /// and it **may** panic if the destructor has previously been run for this thread.
727 /// #![feature(local_key_cell_methods)]
728 /// use std::cell::RefCell;
731 /// static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
734 /// X.with_borrow_mut(|v| v.push(1));
736 /// let a = X.take();
738 /// assert_eq!(a, vec![1]);
740 /// X.with_borrow(|v| assert!(v.is_empty()));
742 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
743 pub fn take(&'static self) -> T
747 self.with(|cell| cell.take())
750 /// Replaces the contained value, returning the old value.
754 /// Panics if the value is currently borrowed.
756 /// Panics if the key currently has its destructor running,
757 /// and it **may** panic if the destructor has previously been run for this thread.
762 /// #![feature(local_key_cell_methods)]
763 /// use std::cell::RefCell;
766 /// static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
769 /// let prev = X.replace(vec![1, 2, 3]);
770 /// assert!(prev.is_empty());
772 /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
774 #[unstable(feature = "local_key_cell_methods", issue = "92122")]
775 pub fn replace(&'static self, value: T) -> T {
776 self.with(|cell| cell.replace(value))
781 use crate::cell::UnsafeCell;
785 pub struct LazyKeyInner<T> {
786 inner: UnsafeCell<Option<T>>,
789 impl<T> LazyKeyInner<T> {
790 pub const fn new() -> LazyKeyInner<T> {
791 LazyKeyInner { inner: UnsafeCell::new(None) }
794 pub unsafe fn get(&self) -> Option<&'static T> {
795 // SAFETY: The caller must ensure no reference is ever handed out to
796 // the inner cell nor mutable reference to the Option<T> inside said
797 // cell. This make it safe to hand a reference, though the lifetime
798 // of 'static is itself unsafe, making the get method unsafe.
799 unsafe { (*self.inner.get()).as_ref() }
802 /// The caller must ensure that no reference is active: this method
803 /// needs unique access.
804 pub unsafe fn initialize<F: FnOnce() -> T>(&self, init: F) -> &'static T {
805 // Execute the initialization up front, *then* move it into our slot,
806 // just in case initialization fails.
808 let ptr = self.inner.get();
812 // note that this can in theory just be `*ptr = Some(value)`, but due to
813 // the compiler will currently codegen that pattern with something like:
815 // ptr::drop_in_place(ptr)
816 // ptr::write(ptr, Some(value))
818 // Due to this pattern it's possible for the destructor of the value in
819 // `ptr` (e.g., if this is being recursively initialized) to re-access
820 // TLS, in which case there will be a `&` and `&mut` pointer to the same
821 // value (an aliasing violation). To avoid setting the "I'm running a
822 // destructor" flag we just use `mem::replace` which should sequence the
823 // operations a little differently and make this safe to call.
825 // The precondition also ensures that we are the only one accessing
826 // `self` at the moment so replacing is fine.
828 let _ = mem::replace(&mut *ptr, Some(value));
831 // SAFETY: With the call to `mem::replace` it is guaranteed there is
832 // a `Some` behind `ptr`, not a `None` so `unreachable_unchecked`
833 // will never be reached.
835 // After storing `Some` we want to get a reference to the contents of
836 // what we just stored. While we could use `unwrap` here and it should
837 // always work it empirically doesn't seem to always get optimized away,
838 // which means that using something like `try_with` can pull in
839 // panicking code and cause a large size bloat.
842 None => hint::unreachable_unchecked(),
847 /// The other methods hand out references while taking &self.
848 /// As such, callers of this method must ensure no `&` and `&mut` are
849 /// available and used at the same time.
851 pub unsafe fn take(&mut self) -> Option<T> {
852 // SAFETY: See doc comment for this method.
853 unsafe { (*self.inner.get()).take() }
858 /// On some targets like wasm there's no threads, so no need to generate
859 /// thread locals and we can instead just use plain statics!
861 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
863 use super::lazy::LazyKeyInner;
867 inner: LazyKeyInner<T>,
870 unsafe impl<T> Sync for Key<T> {}
872 impl<T> fmt::Debug for Key<T> {
873 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
874 f.debug_struct("Key").finish_non_exhaustive()
879 pub const fn new() -> Key<T> {
880 Key { inner: LazyKeyInner::new() }
883 pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> {
884 // SAFETY: The caller must ensure no reference is ever handed out to
885 // the inner cell nor mutable reference to the Option<T> inside said
886 // cell. This make it safe to hand a reference, though the lifetime
887 // of 'static is itself unsafe, making the get method unsafe.
889 match self.inner.get() {
890 Some(ref value) => value,
891 None => self.inner.initialize(init),
901 #[cfg(target_thread_local)]
903 use super::lazy::LazyKeyInner;
904 use crate::cell::Cell;
907 use crate::sys::thread_local_dtor::register_dtor;
909 #[derive(Copy, Clone)]
916 // This data structure has been carefully constructed so that the fast path
917 // only contains one branch on x86. That optimization is necessary to avoid
918 // duplicated tls lookups on OSX.
920 // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
922 // If `LazyKeyInner::get` returns `None`, that indicates either:
923 // * The value has never been initialized
924 // * The value is being recursively initialized
925 // * The value has already been destroyed or is being destroyed
926 // To determine which kind of `None`, check `dtor_state`.
928 // This is very optimizer friendly for the fast path - initialized but
930 inner: LazyKeyInner<T>,
932 // Metadata to keep track of the state of the destructor. Remember that
933 // this variable is thread-local, not global.
934 dtor_state: Cell<DtorState>,
937 impl<T> fmt::Debug for Key<T> {
938 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
939 f.debug_struct("Key").finish_non_exhaustive()
944 pub const fn new() -> Key<T> {
945 Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }
948 // note that this is just a publicly-callable function only for the
949 // const-initialized form of thread locals, basically a way to call the
950 // free `register_dtor` function defined elsewhere in libstd.
951 pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
953 register_dtor(a, dtor);
957 pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
958 // SAFETY: See the definitions of `LazyKeyInner::get` and
959 // `try_initialize` for more information.
961 // The caller must ensure no mutable references are ever active to
962 // the inner cell or the inner T when this is called.
963 // The `try_initialize` is dependant on the passed `init` function
966 match self.inner.get() {
967 Some(val) => Some(val),
968 None => self.try_initialize(init),
973 // `try_initialize` is only called once per fast thread local variable,
974 // except in corner cases where thread_local dtors reference other
975 // thread_local's, or it is being recursively initialized.
977 // Macos: Inlining this function can cause two `tlv_get_addr` calls to
978 // be performed for every call to `Key::get`.
979 // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
981 unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
982 // SAFETY: See comment above (this function doc).
983 if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } {
984 // SAFETY: See comment above (this function doc).
985 Some(unsafe { self.inner.initialize(init) })
991 // `try_register_dtor` is only called once per fast thread local
992 // variable, except in corner cases where thread_local dtors reference
993 // other thread_local's, or it is being recursively initialized.
994 unsafe fn try_register_dtor(&self) -> bool {
995 match self.dtor_state.get() {
996 DtorState::Unregistered => {
997 // SAFETY: dtor registration happens before initialization.
998 // Passing `self` as a pointer while using `destroy_value<T>`
999 // is safe because the function will build a pointer to a
1000 // Key<T>, which is the type of self and so find the correct
1002 unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::<T>) };
1003 self.dtor_state.set(DtorState::Registered);
1006 DtorState::Registered => {
1007 // recursively initialized
1010 DtorState::RunningOrHasRun => false,
1015 unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) {
1016 let ptr = ptr as *mut Key<T>;
1020 // The pointer `ptr` has been built just above and comes from
1021 // `try_register_dtor` where it is originally a Key<T> coming from `self`,
1022 // making it non-NUL and of the correct type.
1024 // Right before we run the user destructor be sure to set the
1025 // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
1026 // causes future calls to `get` to run `try_initialize_drop` again,
1027 // which will now fail, and return `None`.
1029 let value = (*ptr).inner.take();
1030 (*ptr).dtor_state.set(DtorState::RunningOrHasRun);
1038 use super::lazy::LazyKeyInner;
1039 use crate::cell::Cell;
1043 use crate::sys_common::thread_local_key::StaticKey as OsStaticKey;
1046 // OS-TLS key that we'll use to key off.
1048 marker: marker::PhantomData<Cell<T>>,
1051 impl<T> fmt::Debug for Key<T> {
1052 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1053 f.debug_struct("Key").finish_non_exhaustive()
1057 unsafe impl<T> Sync for Key<T> {}
1059 struct Value<T: 'static> {
1060 inner: LazyKeyInner<T>,
1061 key: &'static Key<T>,
1064 impl<T: 'static> Key<T> {
1065 #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
1066 pub const fn new() -> Key<T> {
1067 Key { os: OsStaticKey::new(Some(destroy_value::<T>)), marker: marker::PhantomData }
1070 /// It is a requirement for the caller to ensure that no mutable
1071 /// reference is active when this method is called.
1072 pub unsafe fn get(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> {
1073 // SAFETY: See the documentation for this method.
1074 let ptr = unsafe { self.os.get() as *mut Value<T> };
1076 // SAFETY: the check ensured the pointer is safe (its destructor
1077 // is not running) + it is coming from a trusted source (self).
1078 if let Some(ref value) = unsafe { (*ptr).inner.get() } {
1082 // SAFETY: At this point we are sure we have no value and so
1083 // initializing (or trying to) is safe.
1084 unsafe { self.try_initialize(init) }
1087 // `try_initialize` is only called once per os thread local variable,
1088 // except in corner cases where thread_local dtors reference other
1089 // thread_local's, or it is being recursively initialized.
1090 unsafe fn try_initialize(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> {
1091 // SAFETY: No mutable references are ever handed out meaning getting
1093 let ptr = unsafe { self.os.get() as *mut Value<T> };
1094 if ptr.addr() == 1 {
1095 // destructor is running
1099 let ptr = if ptr.is_null() {
1100 // If the lookup returned null, we haven't initialized our own
1101 // local copy, so do that now.
1102 let ptr: Box<Value<T>> = box Value { inner: LazyKeyInner::new(), key: self };
1103 let ptr = Box::into_raw(ptr);
1104 // SAFETY: At this point we are sure there is no value inside
1105 // ptr so setting it will not affect anyone else.
1107 self.os.set(ptr as *mut u8);
1111 // recursive initialization
1115 // SAFETY: ptr has been ensured as non-NUL just above an so can be
1116 // dereferenced safely.
1117 unsafe { Some((*ptr).inner.initialize(init)) }
1121 unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) {
1124 // The OS TLS ensures that this key contains a null value when this
1125 // destructor starts to run. We set it back to a sentinel value of 1 to
1126 // ensure that any future calls to `get` for this thread will return
1129 // Note that to prevent an infinite loop we reset it back to null right
1130 // before we return from the destructor ourselves.
1132 let ptr = Box::from_raw(ptr as *mut Value<T>);
1134 key.os.set(ptr::invalid_mut(1));
1136 key.os.set(ptr::null_mut());