std/thread/
local.rs

1//! Thread local storage
2
3#![unstable(feature = "thread_local_internals", issue = "none")]
4
5use crate::cell::{Cell, RefCell};
6use crate::error::Error;
7use crate::fmt;
8
9/// A thread local storage (TLS) key which owns its contents.
10///
11/// This key uses the fastest possible implementation available to it for the
12/// target platform. It is instantiated with the [`thread_local!`] macro and the
13/// primary method is the [`with`] method, though there are helpers to make
14/// working with [`Cell`] types easier.
15///
16/// The [`with`] method yields a reference to the contained value which cannot
17/// outlive the current thread or escape the given closure.
18///
19/// [`thread_local!`]: crate::thread_local
20///
21/// # Initialization and Destruction
22///
23/// Initialization is dynamically performed on the first call to a setter (e.g.
24/// [`with`]) within a thread, and values that implement [`Drop`] get
25/// destructed when a thread exits. Some caveats apply, which are explained below.
26///
27/// A `LocalKey`'s initializer cannot recursively depend on itself. Using a
28/// `LocalKey` in this way may cause panics, aborts or infinite recursion on
29/// the first call to `with`.
30///
31/// # Single-thread Synchronization
32///
33/// Though there is no potential race with other threads, it is still possible to
34/// obtain multiple references to the thread-local data in different places on
35/// the call stack. For this reason, only shared (`&T`) references may be obtained.
36///
37/// To allow obtaining an exclusive mutable reference (`&mut T`), typically a
38/// [`Cell`] or [`RefCell`] is used (see the [`std::cell`] for more information
39/// on how exactly this works). To make this easier there are specialized
40/// implementations for [`LocalKey<Cell<T>>`] and [`LocalKey<RefCell<T>>`].
41///
42/// [`std::cell`]: `crate::cell`
43/// [`LocalKey<Cell<T>>`]: struct.LocalKey.html#impl-LocalKey<Cell<T>>
44/// [`LocalKey<RefCell<T>>`]: struct.LocalKey.html#impl-LocalKey<RefCell<T>>
45///
46///
47/// # Examples
48///
49/// ```
50/// use std::cell::Cell;
51/// use std::thread;
52///
53/// thread_local!(static FOO: Cell<u32> = Cell::new(1));
54///
55/// assert_eq!(FOO.get(), 1);
56/// FOO.set(2);
57///
58/// // each thread starts out with the initial value of 1
59/// let t = thread::spawn(move || {
60///     assert_eq!(FOO.get(), 1);
61///     FOO.set(3);
62/// });
63///
64/// // wait for the thread to complete and bail out on panic
65/// t.join().unwrap();
66///
67/// // we retain our original value of 2 despite the child thread
68/// assert_eq!(FOO.get(), 2);
69/// ```
70///
71/// # Platform-specific behavior
72///
73/// Note that a "best effort" is made to ensure that destructors for types
74/// stored in thread local storage are run, but not all platforms can guarantee
75/// that destructors will be run for all types in thread local storage. For
76/// example, there are a number of known caveats where destructors are not run:
77///
78/// 1. On Unix systems when pthread-based TLS is being used, destructors will
79///    not be run for TLS values on the main thread when it exits. Note that the
80///    application will exit immediately after the main thread exits as well.
81/// 2. On all platforms it's possible for TLS to re-initialize other TLS slots
82///    during destruction. Some platforms ensure that this cannot happen
83///    infinitely by preventing re-initialization of any slot that has been
84///    destroyed, but not all platforms have this guard. Those platforms that do
85///    not guard typically have a synthetic limit after which point no more
86///    destructors are run.
87/// 3. When the process exits on Windows systems, TLS destructors may only be
88///    run on the thread that causes the process to exit. This is because the
89///    other threads may be forcibly terminated.
90///
91/// ## Synchronization in thread-local destructors
92///
93/// On Windows, synchronization operations (such as [`JoinHandle::join`]) in
94/// thread local destructors are prone to deadlocks and so should be avoided.
95/// This is because the [loader lock] is held while a destructor is run. The
96/// lock is acquired whenever a thread starts or exits or when a DLL is loaded
97/// or unloaded. Therefore these events are blocked for as long as a thread
98/// local destructor is running.
99///
100/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
101/// [`JoinHandle::join`]: crate::thread::JoinHandle::join
102/// [`with`]: LocalKey::with
103#[cfg_attr(not(test), rustc_diagnostic_item = "LocalKey")]
104#[stable(feature = "rust1", since = "1.0.0")]
105pub struct LocalKey<T: 'static> {
106    // This outer `LocalKey<T>` type is what's going to be stored in statics,
107    // but actual data inside will sometimes be tagged with #[thread_local].
108    // It's not valid for a true static to reference a #[thread_local] static,
109    // so we get around that by exposing an accessor through a layer of function
110    // indirection (this thunk).
111    //
112    // Note that the thunk is itself unsafe because the returned lifetime of the
113    // slot where data lives, `'static`, is not actually valid. The lifetime
114    // here is actually slightly shorter than the currently running thread!
115    //
116    // Although this is an extra layer of indirection, it should in theory be
117    // trivially devirtualizable by LLVM because the value of `inner` never
118    // changes and the constant should be readonly within a crate. This mainly
119    // only runs into problems when TLS statics are exported across crates.
120    inner: fn(Option<&mut Option<T>>) -> *const T,
121}
122
123#[stable(feature = "std_debug", since = "1.16.0")]
124impl<T: 'static> fmt::Debug for LocalKey<T> {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        f.debug_struct("LocalKey").finish_non_exhaustive()
127    }
128}
129
130/// Declare a new thread local storage key of type [`std::thread::LocalKey`].
131///
132/// # Syntax
133///
134/// The macro wraps any number of static declarations and makes them thread local.
135/// Publicity and attributes for each static are allowed. Example:
136///
137/// ```
138/// use std::cell::{Cell, RefCell};
139///
140/// thread_local! {
141///     pub static FOO: Cell<u32> = Cell::new(1);
142///
143///     static BAR: RefCell<Vec<f32>> = RefCell::new(vec![1.0, 2.0]);
144/// }
145///
146/// assert_eq!(FOO.get(), 1);
147/// BAR.with_borrow(|v| assert_eq!(v[1], 2.0));
148/// ```
149///
150/// Note that only shared references (`&T`) to the inner data may be obtained, so a
151/// type such as [`Cell`] or [`RefCell`] is typically used to allow mutating access.
152///
153/// This macro supports a special `const {}` syntax that can be used
154/// when the initialization expression can be evaluated as a constant.
155/// This can enable a more efficient thread local implementation that
156/// can avoid lazy initialization. For types that do not
157/// [need to be dropped][crate::mem::needs_drop], this can enable an
158/// even more efficient implementation that does not need to
159/// track any additional state.
160///
161/// ```
162/// use std::cell::RefCell;
163///
164/// thread_local! {
165///     pub static FOO: RefCell<Vec<u32>> = const { RefCell::new(Vec::new()) };
166/// }
167///
168/// FOO.with_borrow(|v| assert_eq!(v.len(), 0));
169/// ```
170///
171/// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
172/// information.
173///
174/// [`std::thread::LocalKey`]: crate::thread::LocalKey
175#[macro_export]
176#[stable(feature = "rust1", since = "1.0.0")]
177#[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")]
178#[allow_internal_unstable(thread_local_internals)]
179macro_rules! thread_local {
180    // empty (base case for the recursion)
181    () => {};
182
183    ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block; $($rest:tt)*) => (
184        $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
185        $crate::thread_local!($($rest)*);
186    );
187
188    ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block) => (
189        $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
190    );
191
192    // process multiple declarations
193    ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
194        $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
195        $crate::thread_local!($($rest)*);
196    );
197
198    // handle a single declaration
199    ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
200        $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
201    );
202}
203
204/// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
205#[stable(feature = "thread_local_try_with", since = "1.26.0")]
206#[non_exhaustive]
207#[derive(Clone, Copy, Eq, PartialEq)]
208pub struct AccessError;
209
210#[stable(feature = "thread_local_try_with", since = "1.26.0")]
211impl fmt::Debug for AccessError {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        f.debug_struct("AccessError").finish()
214    }
215}
216
217#[stable(feature = "thread_local_try_with", since = "1.26.0")]
218impl fmt::Display for AccessError {
219    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220        fmt::Display::fmt("already destroyed", f)
221    }
222}
223
224#[stable(feature = "thread_local_try_with", since = "1.26.0")]
225impl Error for AccessError {}
226
227// This ensures the panicking code is outlined from `with` for `LocalKey`.
228#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
229#[track_caller]
230#[cold]
231fn panic_access_error(err: AccessError) -> ! {
232    panic!("cannot access a Thread Local Storage value during or after destruction: {err:?}")
233}
234
235impl<T: 'static> LocalKey<T> {
236    #[doc(hidden)]
237    #[unstable(
238        feature = "thread_local_internals",
239        reason = "recently added to create a key",
240        issue = "none"
241    )]
242    pub const unsafe fn new(inner: fn(Option<&mut Option<T>>) -> *const T) -> LocalKey<T> {
243        LocalKey { inner }
244    }
245
246    /// Acquires a reference to the value in this TLS key.
247    ///
248    /// This will lazily initialize the value if this thread has not referenced
249    /// this key yet.
250    ///
251    /// # Panics
252    ///
253    /// This function will `panic!()` if the key currently has its
254    /// destructor running, and it **may** panic if the destructor has
255    /// previously been run for this thread.
256    ///
257    /// # Examples
258    ///
259    /// ```
260    /// thread_local! {
261    ///     pub static STATIC: String = String::from("I am");
262    /// }
263    ///
264    /// assert_eq!(
265    ///     STATIC.with(|original_value| format!("{original_value} initialized")),
266    ///     "I am initialized",
267    /// );
268    /// ```
269    #[stable(feature = "rust1", since = "1.0.0")]
270    pub fn with<F, R>(&'static self, f: F) -> R
271    where
272        F: FnOnce(&T) -> R,
273    {
274        match self.try_with(f) {
275            Ok(r) => r,
276            Err(err) => panic_access_error(err),
277        }
278    }
279
280    /// Acquires a reference to the value in this TLS key.
281    ///
282    /// This will lazily initialize the value if this thread has not referenced
283    /// this key yet. If the key has been destroyed (which may happen if this is called
284    /// in a destructor), this function will return an [`AccessError`].
285    ///
286    /// # Panics
287    ///
288    /// This function will still `panic!()` if the key is uninitialized and the
289    /// key's initializer panics.
290    ///
291    /// # Examples
292    ///
293    /// ```
294    /// thread_local! {
295    ///     pub static STATIC: String = String::from("I am");
296    /// }
297    ///
298    /// assert_eq!(
299    ///     STATIC.try_with(|original_value| format!("{original_value} initialized")),
300    ///     Ok(String::from("I am initialized")),
301    /// );
302    /// ```
303    #[stable(feature = "thread_local_try_with", since = "1.26.0")]
304    #[inline]
305    pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
306    where
307        F: FnOnce(&T) -> R,
308    {
309        let thread_local = unsafe { (self.inner)(None).as_ref().ok_or(AccessError)? };
310        Ok(f(thread_local))
311    }
312
313    /// Acquires a reference to the value in this TLS key, initializing it with
314    /// `init` if it wasn't already initialized on this thread.
315    ///
316    /// If `init` was used to initialize the thread local variable, `None` is
317    /// passed as the first argument to `f`. If it was already initialized,
318    /// `Some(init)` is passed to `f`.
319    ///
320    /// # Panics
321    ///
322    /// This function will panic if the key currently has its destructor
323    /// running, and it **may** panic if the destructor has previously been run
324    /// for this thread.
325    fn initialize_with<F, R>(&'static self, init: T, f: F) -> R
326    where
327        F: FnOnce(Option<T>, &T) -> R,
328    {
329        let mut init = Some(init);
330
331        let reference = unsafe {
332            match (self.inner)(Some(&mut init)).as_ref() {
333                Some(r) => r,
334                None => panic_access_error(AccessError),
335            }
336        };
337
338        f(init, reference)
339    }
340}
341
342impl<T: 'static> LocalKey<Cell<T>> {
343    /// Sets or initializes the contained value.
344    ///
345    /// Unlike the other methods, this will *not* run the lazy initializer of
346    /// the thread local. Instead, it will be directly initialized with the
347    /// given value if it wasn't initialized yet.
348    ///
349    /// # Panics
350    ///
351    /// Panics if the key currently has its destructor running,
352    /// and it **may** panic if the destructor has previously been run for this thread.
353    ///
354    /// # Examples
355    ///
356    /// ```
357    /// use std::cell::Cell;
358    ///
359    /// thread_local! {
360    ///     static X: Cell<i32> = panic!("!");
361    /// }
362    ///
363    /// // Calling X.get() here would result in a panic.
364    ///
365    /// X.set(123); // But X.set() is fine, as it skips the initializer above.
366    ///
367    /// assert_eq!(X.get(), 123);
368    /// ```
369    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
370    pub fn set(&'static self, value: T) {
371        self.initialize_with(Cell::new(value), |value, cell| {
372            if let Some(value) = value {
373                // The cell was already initialized, so `value` wasn't used to
374                // initialize it. So we overwrite the current value with the
375                // new one instead.
376                cell.set(value.into_inner());
377            }
378        });
379    }
380
381    /// Returns a copy of the contained value.
382    ///
383    /// This will lazily initialize the value if this thread has not referenced
384    /// this key yet.
385    ///
386    /// # Panics
387    ///
388    /// Panics if the key currently has its destructor running,
389    /// and it **may** panic if the destructor has previously been run for this thread.
390    ///
391    /// # Examples
392    ///
393    /// ```
394    /// use std::cell::Cell;
395    ///
396    /// thread_local! {
397    ///     static X: Cell<i32> = Cell::new(1);
398    /// }
399    ///
400    /// assert_eq!(X.get(), 1);
401    /// ```
402    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
403    pub fn get(&'static self) -> T
404    where
405        T: Copy,
406    {
407        self.with(Cell::get)
408    }
409
410    /// Takes the contained value, leaving `Default::default()` in its place.
411    ///
412    /// This will lazily initialize the value if this thread has not referenced
413    /// this key yet.
414    ///
415    /// # Panics
416    ///
417    /// Panics if the key currently has its destructor running,
418    /// and it **may** panic if the destructor has previously been run for this thread.
419    ///
420    /// # Examples
421    ///
422    /// ```
423    /// use std::cell::Cell;
424    ///
425    /// thread_local! {
426    ///     static X: Cell<Option<i32>> = Cell::new(Some(1));
427    /// }
428    ///
429    /// assert_eq!(X.take(), Some(1));
430    /// assert_eq!(X.take(), None);
431    /// ```
432    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
433    pub fn take(&'static self) -> T
434    where
435        T: Default,
436    {
437        self.with(Cell::take)
438    }
439
440    /// Replaces the contained value, returning the old value.
441    ///
442    /// This will lazily initialize the value if this thread has not referenced
443    /// this key yet.
444    ///
445    /// # Panics
446    ///
447    /// Panics if the key currently has its destructor running,
448    /// and it **may** panic if the destructor has previously been run for this thread.
449    ///
450    /// # Examples
451    ///
452    /// ```
453    /// use std::cell::Cell;
454    ///
455    /// thread_local! {
456    ///     static X: Cell<i32> = Cell::new(1);
457    /// }
458    ///
459    /// assert_eq!(X.replace(2), 1);
460    /// assert_eq!(X.replace(3), 2);
461    /// ```
462    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
463    #[rustc_confusables("swap")]
464    pub fn replace(&'static self, value: T) -> T {
465        self.with(|cell| cell.replace(value))
466    }
467}
468
469impl<T: 'static> LocalKey<RefCell<T>> {
470    /// Acquires a reference to the contained value.
471    ///
472    /// This will lazily initialize the value if this thread has not referenced
473    /// this key yet.
474    ///
475    /// # Panics
476    ///
477    /// Panics if the value is currently mutably borrowed.
478    ///
479    /// Panics if the key currently has its destructor running,
480    /// and it **may** panic if the destructor has previously been run for this thread.
481    ///
482    /// # Examples
483    ///
484    /// ```
485    /// use std::cell::RefCell;
486    ///
487    /// thread_local! {
488    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
489    /// }
490    ///
491    /// X.with_borrow(|v| assert!(v.is_empty()));
492    /// ```
493    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
494    pub fn with_borrow<F, R>(&'static self, f: F) -> R
495    where
496        F: FnOnce(&T) -> R,
497    {
498        self.with(|cell| f(&cell.borrow()))
499    }
500
501    /// Acquires a mutable reference to the contained value.
502    ///
503    /// This will lazily initialize the value if this thread has not referenced
504    /// this key yet.
505    ///
506    /// # Panics
507    ///
508    /// Panics if the value is currently borrowed.
509    ///
510    /// Panics if the key currently has its destructor running,
511    /// and it **may** panic if the destructor has previously been run for this thread.
512    ///
513    /// # Examples
514    ///
515    /// ```
516    /// use std::cell::RefCell;
517    ///
518    /// thread_local! {
519    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
520    /// }
521    ///
522    /// X.with_borrow_mut(|v| v.push(1));
523    ///
524    /// X.with_borrow(|v| assert_eq!(*v, vec![1]));
525    /// ```
526    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
527    pub fn with_borrow_mut<F, R>(&'static self, f: F) -> R
528    where
529        F: FnOnce(&mut T) -> R,
530    {
531        self.with(|cell| f(&mut cell.borrow_mut()))
532    }
533
534    /// Sets or initializes the contained value.
535    ///
536    /// Unlike the other methods, this will *not* run the lazy initializer of
537    /// the thread local. Instead, it will be directly initialized with the
538    /// given value if it wasn't initialized yet.
539    ///
540    /// # Panics
541    ///
542    /// Panics if the value is currently borrowed.
543    ///
544    /// Panics if the key currently has its destructor running,
545    /// and it **may** panic if the destructor has previously been run for this thread.
546    ///
547    /// # Examples
548    ///
549    /// ```
550    /// use std::cell::RefCell;
551    ///
552    /// thread_local! {
553    ///     static X: RefCell<Vec<i32>> = panic!("!");
554    /// }
555    ///
556    /// // Calling X.with() here would result in a panic.
557    ///
558    /// X.set(vec![1, 2, 3]); // But X.set() is fine, as it skips the initializer above.
559    ///
560    /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
561    /// ```
562    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
563    pub fn set(&'static self, value: T) {
564        self.initialize_with(RefCell::new(value), |value, cell| {
565            if let Some(value) = value {
566                // The cell was already initialized, so `value` wasn't used to
567                // initialize it. So we overwrite the current value with the
568                // new one instead.
569                *cell.borrow_mut() = value.into_inner();
570            }
571        });
572    }
573
574    /// Takes the contained value, leaving `Default::default()` in its place.
575    ///
576    /// This will lazily initialize the value if this thread has not referenced
577    /// this key yet.
578    ///
579    /// # Panics
580    ///
581    /// Panics if the value is currently borrowed.
582    ///
583    /// Panics if the key currently has its destructor running,
584    /// and it **may** panic if the destructor has previously been run for this thread.
585    ///
586    /// # Examples
587    ///
588    /// ```
589    /// use std::cell::RefCell;
590    ///
591    /// thread_local! {
592    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
593    /// }
594    ///
595    /// X.with_borrow_mut(|v| v.push(1));
596    ///
597    /// let a = X.take();
598    ///
599    /// assert_eq!(a, vec![1]);
600    ///
601    /// X.with_borrow(|v| assert!(v.is_empty()));
602    /// ```
603    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
604    pub fn take(&'static self) -> T
605    where
606        T: Default,
607    {
608        self.with(RefCell::take)
609    }
610
611    /// Replaces the contained value, returning the old value.
612    ///
613    /// # Panics
614    ///
615    /// Panics if the value is currently borrowed.
616    ///
617    /// Panics if the key currently has its destructor running,
618    /// and it **may** panic if the destructor has previously been run for this thread.
619    ///
620    /// # Examples
621    ///
622    /// ```
623    /// use std::cell::RefCell;
624    ///
625    /// thread_local! {
626    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
627    /// }
628    ///
629    /// let prev = X.replace(vec![1, 2, 3]);
630    /// assert!(prev.is_empty());
631    ///
632    /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
633    /// ```
634    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
635    #[rustc_confusables("swap")]
636    pub fn replace(&'static self, value: T) -> T {
637        self.with(|cell| cell.replace(value))
638    }
639}