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 implementation available on the target platform.
12/// 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 platform-specific caveats apply, which
26/// are explained below.
27/// Note that, should the destructor panic, the whole process will be [aborted].
28/// On platforms where initialization requires memory allocation, this is
29/// performed directly through [`System`], allowing the [global allocator]
30/// to make use of thread local storage.
31///
32/// A `LocalKey`'s initializer cannot recursively depend on itself. Using a
33/// `LocalKey` in this way may cause panics, aborts, or infinite recursion on
34/// the first call to `with`.
35///
36/// [`System`]: crate::alloc::System
37/// [global allocator]: crate::alloc
38/// [aborted]: crate::process::abort
39///
40/// # Single-thread Synchronization
41///
42/// Though there is no potential race with other threads, it is still possible to
43/// obtain multiple references to the thread-local data in different places on
44/// the call stack. For this reason, only shared (`&T`) references may be obtained.
45///
46/// To allow obtaining an exclusive mutable reference (`&mut T`), typically a
47/// [`Cell`] or [`RefCell`] is used (see the [`std::cell`] for more information
48/// on how exactly this works). To make this easier there are specialized
49/// implementations for [`LocalKey<Cell<T>>`] and [`LocalKey<RefCell<T>>`].
50///
51/// [`std::cell`]: `crate::cell`
52/// [`LocalKey<Cell<T>>`]: struct.LocalKey.html#impl-LocalKey<Cell<T>>
53/// [`LocalKey<RefCell<T>>`]: struct.LocalKey.html#impl-LocalKey<RefCell<T>>
54///
55///
56/// # Examples
57///
58/// ```
59/// use std::cell::Cell;
60/// use std::thread;
61///
62/// // explicit `const {}` block enables more efficient initialization
63/// thread_local!(static FOO: Cell<u32> = const { Cell::new(1) });
64///
65/// assert_eq!(FOO.get(), 1);
66/// FOO.set(2);
67///
68/// // each thread starts out with the initial value of 1
69/// let t = thread::spawn(move || {
70///     assert_eq!(FOO.get(), 1);
71///     FOO.set(3);
72/// });
73///
74/// // wait for the thread to complete and bail out on panic
75/// t.join().unwrap();
76///
77/// // we retain our original value of 2 despite the child thread
78/// assert_eq!(FOO.get(), 2);
79/// ```
80///
81/// # Platform-specific behavior
82///
83/// Note that a "best effort" is made to ensure that destructors for types
84/// stored in thread local storage are run, but not all platforms can guarantee
85/// that destructors will be run for all types in thread local storage. For
86/// example, there are a number of known caveats where destructors are not run:
87///
88/// 1. On Unix systems when pthread-based TLS is being used, destructors will
89///    not be run for TLS values on the main thread when it exits. Note that the
90///    application will exit immediately after the main thread exits as well.
91/// 2. On all platforms it's possible for TLS to re-initialize other TLS slots
92///    during destruction. Some platforms ensure that this cannot happen
93///    infinitely by preventing re-initialization of any slot that has been
94///    destroyed, but not all platforms have this guard. Those platforms that do
95///    not guard typically have a synthetic limit after which point no more
96///    destructors are run.
97/// 3. When the process exits on Windows systems, TLS destructors may only be
98///    run on the thread that causes the process to exit. This is because the
99///    other threads may be forcibly terminated.
100///
101/// ## Synchronization in thread-local destructors
102///
103/// On Windows, synchronization operations (such as [`JoinHandle::join`]) in
104/// thread local destructors are prone to deadlocks and so should be avoided.
105/// This is because the [loader lock] is held while a destructor is run. The
106/// lock is acquired whenever a thread starts or exits or when a DLL is loaded
107/// or unloaded. Therefore these events are blocked for as long as a thread
108/// local destructor is running.
109///
110/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
111/// [`JoinHandle::join`]: crate::thread::JoinHandle::join
112/// [`with`]: LocalKey::with
113#[cfg_attr(not(test), rustc_diagnostic_item = "LocalKey")]
114#[stable(feature = "rust1", since = "1.0.0")]
115pub struct LocalKey<T: 'static> {
116    // This outer `LocalKey<T>` type is what's going to be stored in statics,
117    // but actual data inside will sometimes be tagged with #[thread_local].
118    // It's not valid for a true static to reference a #[thread_local] static,
119    // so we get around that by exposing an accessor through a layer of function
120    // indirection (this thunk).
121    //
122    // Note that the thunk is itself unsafe because the returned lifetime of the
123    // slot where data lives, `'static`, is not actually valid. The lifetime
124    // here is actually slightly shorter than the currently running thread!
125    //
126    // Although this is an extra layer of indirection, it should in theory be
127    // trivially devirtualizable by LLVM because the value of `inner` never
128    // changes and the constant should be readonly within a crate. This mainly
129    // only runs into problems when TLS statics are exported across crates.
130    inner: fn(Option<&mut Option<T>>) -> *const T,
131}
132
133#[stable(feature = "std_debug", since = "1.16.0")]
134impl<T: 'static> fmt::Debug for LocalKey<T> {
135    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136        f.debug_struct("LocalKey").finish_non_exhaustive()
137    }
138}
139
140#[doc(hidden)]
141#[allow_internal_unstable(thread_local_internals)]
142#[unstable(feature = "thread_local_internals", issue = "none")]
143#[rustc_macro_transparency = "semitransparent"]
144pub macro thread_local_process_attrs {
145
146    // Parse `cfg_attr` to figure out whether it's a `rustc_align_static`.
147    // Each `cfg_attr` can have zero or more attributes on the RHS, and can be nested.
148
149    // finished parsing the `cfg_attr`, it had no `rustc_align_static`
150    (
151        [] [$(#[$($prev_other_attrs:tt)*])*];
152        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [] };
153        [$($prev_align_attrs_ret:tt)*] [$($prev_other_attrs_ret:tt)*];
154        $($rest:tt)*
155    ) => (
156        $crate::thread::local_impl::thread_local_process_attrs!(
157            [$($prev_align_attrs_ret)*] [$($prev_other_attrs_ret)* #[cfg_attr($($predicate)*, $($($prev_other_attrs)*),*)]];
158            $($rest)*
159        );
160    ),
161
162    // finished parsing the `cfg_attr`, it had nothing but `rustc_align_static`
163    (
164        [$(#[$($prev_align_attrs:tt)*])+] [];
165        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [] };
166        [$($prev_align_attrs_ret:tt)*] [$($prev_other_attrs_ret:tt)*];
167        $($rest:tt)*
168    ) => (
169        $crate::thread::local_impl::thread_local_process_attrs!(
170            [$($prev_align_attrs_ret)*  #[cfg_attr($($predicate)*, $($($prev_align_attrs)*),+)]] [$($prev_other_attrs_ret)*];
171            $($rest)*
172        );
173    ),
174
175    // finished parsing the `cfg_attr`, it had a mix of `rustc_align_static` and other attrs
176    (
177        [$(#[$($prev_align_attrs:tt)*])+] [$(#[$($prev_other_attrs:tt)*])+];
178        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [] };
179        [$($prev_align_attrs_ret:tt)*] [$($prev_other_attrs_ret:tt)*];
180        $($rest:tt)*
181    ) => (
182        $crate::thread::local_impl::thread_local_process_attrs!(
183            [$($prev_align_attrs_ret)*  #[cfg_attr($($predicate)*, $($($prev_align_attrs)*),+)]] [$($prev_other_attrs_ret)* #[cfg_attr($($predicate)*, $($($prev_other_attrs)*),+)]];
184            $($rest)*
185        );
186    ),
187
188    // it's a `rustc_align_static`
189    (
190        [$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
191        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [rustc_align_static($($align_static_args:tt)*) $(, $($attr_rhs:tt)*)?] };
192        $($rest:tt)*
193    ) => (
194        $crate::thread::local_impl::thread_local_process_attrs!(
195            [$($prev_align_attrs)* #[rustc_align_static($($align_static_args)*)]] [$($prev_other_attrs)*];
196            @processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
197            $($rest)*
198        );
199    ),
200
201    // it's a nested `cfg_attr(true, ...)`; recurse into RHS
202    (
203        [$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
204        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr(true, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
205        $($rest:tt)*
206    ) => (
207        $crate::thread::local_impl::thread_local_process_attrs!(
208            [] [];
209            @processing_cfg_attr { pred: (true), rhs: [$($cfg_rhs)*] };
210            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
211            @processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
212            $($rest)*
213        );
214    ),
215
216    // it's a nested `cfg_attr(false, ...)`; recurse into RHS
217    (
218        [$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
219        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr(false, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
220        $($rest:tt)*
221    ) => (
222        $crate::thread::local_impl::thread_local_process_attrs!(
223            [] [];
224            @processing_cfg_attr { pred: (false), rhs: [$($cfg_rhs)*] };
225            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
226            @processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
227            $($rest)*
228        );
229    ),
230
231
232    // it's a nested `cfg_attr(..., ...)`; recurse into RHS
233    (
234        [$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
235        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr($cfg_lhs:meta, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
236        $($rest:tt)*
237    ) => (
238        $crate::thread::local_impl::thread_local_process_attrs!(
239            [] [];
240            @processing_cfg_attr { pred: ($cfg_lhs), rhs: [$($cfg_rhs)*] };
241            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
242            @processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
243            $($rest)*
244        );
245    ),
246
247    // it's some other attribute
248    (
249        [$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
250        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [$meta:meta $(, $($attr_rhs:tt)*)?] };
251        $($rest:tt)*
252    ) => (
253        $crate::thread::local_impl::thread_local_process_attrs!(
254            [$($prev_align_attrs)*] [$($prev_other_attrs)* #[$meta]];
255            @processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
256            $($rest)*
257        );
258    ),
259
260
261    // Separate attributes into `rustc_align_static` and everything else:
262
263    // `rustc_align_static` attribute
264    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[rustc_align_static $($attr_rest:tt)*] $($rest:tt)*) => (
265        $crate::thread::local_impl::thread_local_process_attrs!(
266            [$($prev_align_attrs)* #[rustc_align_static $($attr_rest)*]] [$($prev_other_attrs)*];
267            $($rest)*
268        );
269    ),
270
271    // `cfg_attr(true, ...)` attribute; parse it
272    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr(true, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
273        $crate::thread::local_impl::thread_local_process_attrs!(
274            [] [];
275            @processing_cfg_attr { pred: (true), rhs: [$($cfg_rhs)*] };
276            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
277            $($rest)*
278        );
279    ),
280
281    // `cfg_attr(false, ...)` attribute; parse it
282    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr(false, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
283        $crate::thread::local_impl::thread_local_process_attrs!(
284            [] [];
285            @processing_cfg_attr { pred: (false), rhs: [$($cfg_rhs)*] };
286            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
287            $($rest)*
288        );
289    ),
290
291    // `cfg_attr(..., ...)` attribute; parse it
292    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr($cfg_pred:meta, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
293        $crate::thread::local_impl::thread_local_process_attrs!(
294            [] [];
295            @processing_cfg_attr { pred: ($cfg_pred), rhs: [$($cfg_rhs)*] };
296            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
297            $($rest)*
298        );
299    ),
300
301    // doc comment not followed by any other attributes; process it all at once to avoid blowing recursion limit
302    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; $(#[doc $($doc_rhs:tt)*])+ $vis:vis static $($rest:tt)*) => (
303        $crate::thread::local_impl::thread_local_process_attrs!(
304            [$($prev_align_attrs)*] [$($prev_other_attrs)* $(#[doc $($doc_rhs)*])+];
305            $vis static $($rest)*
306        );
307    ),
308
309    // 8 lines of doc comment; process them all at once to avoid blowing recursion limit
310    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
311     #[doc $($doc_rhs_1:tt)*] #[doc $($doc_rhs_2:tt)*] #[doc $($doc_rhs_3:tt)*] #[doc $($doc_rhs_4:tt)*]
312     #[doc $($doc_rhs_5:tt)*] #[doc $($doc_rhs_6:tt)*] #[doc $($doc_rhs_7:tt)*] #[doc $($doc_rhs_8:tt)*]
313     $($rest:tt)*) => (
314        $crate::thread::local_impl::thread_local_process_attrs!(
315            [$($prev_align_attrs)*] [$($prev_other_attrs)*
316            #[doc $($doc_rhs_1)*] #[doc $($doc_rhs_2)*] #[doc $($doc_rhs_3)*] #[doc $($doc_rhs_4)*]
317            #[doc $($doc_rhs_5)*] #[doc $($doc_rhs_6)*] #[doc $($doc_rhs_7)*] #[doc $($doc_rhs_8)*]];
318            $($rest)*
319        );
320    ),
321
322    // other attribute
323    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[$($attr:tt)*] $($rest:tt)*) => (
324        $crate::thread::local_impl::thread_local_process_attrs!(
325            [$($prev_align_attrs)*] [$($prev_other_attrs)* #[$($attr)*]];
326            $($rest)*
327        );
328    ),
329
330
331    // Delegate to `thread_local_inner` once attributes are fully categorized:
332
333    // process `const` declaration and recurse
334    ([$($align_attrs:tt)*] [$($other_attrs:tt)*]; $vis:vis static $name:ident: $t:ty = const $init:block $(; $($($rest:tt)+)?)?) => (
335        $($other_attrs)* $vis const $name: $crate::thread::LocalKey<$t> =
336            $crate::thread::local_impl::thread_local_inner!(@key $t, $($align_attrs)*, const $init);
337
338        $($($crate::thread::local_impl::thread_local_process_attrs!([] []; $($rest)+);)?)?
339    ),
340
341    // process non-`const` declaration and recurse
342    ([$($align_attrs:tt)*] [$($other_attrs:tt)*]; $vis:vis static $name:ident: $t:ty = $init:expr $(; $($($rest:tt)+)?)?) => (
343        $($other_attrs)* $vis const $name: $crate::thread::LocalKey<$t> =
344            $crate::thread::local_impl::thread_local_inner!(@key $t, $($align_attrs)*, $init);
345
346        $($($crate::thread::local_impl::thread_local_process_attrs!([] []; $($rest)+);)?)?
347    ),
348}
349
350/// Declare a new thread local storage key of type [`std::thread::LocalKey`].
351///
352/// # Syntax
353///
354/// The macro wraps any number of static declarations and makes them thread local.
355/// Publicity and attributes for each static are allowed. Example:
356///
357/// ```
358/// use std::cell::{Cell, RefCell};
359///
360/// thread_local! {
361///     pub static FOO: Cell<u32> = const { Cell::new(1) };
362///
363///     static BAR: RefCell<Vec<f32>> = RefCell::new(vec![1.0, 2.0]);
364/// }
365///
366/// assert_eq!(FOO.get(), 1);
367/// BAR.with_borrow(|v| assert_eq!(v[1], 2.0));
368/// ```
369///
370/// Note that only shared references (`&T`) to the inner data may be obtained, so a
371/// type such as [`Cell`] or [`RefCell`] is typically used to allow mutating access.
372///
373/// This macro supports a special `const {}` syntax that can be used
374/// when the initialization expression can be evaluated as a constant.
375/// This can enable a more efficient thread local implementation that
376/// can avoid lazy initialization. For types that do not
377/// [need to be dropped][crate::mem::needs_drop], this can enable an
378/// even more efficient implementation that does not need to
379/// track any additional state.
380///
381/// ```
382/// use std::cell::RefCell;
383///
384/// thread_local! {
385///     pub static FOO: RefCell<Vec<u32>> = const { RefCell::new(Vec::new()) };
386/// }
387///
388/// FOO.with_borrow(|v| assert_eq!(v.len(), 0));
389/// ```
390///
391/// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
392/// information.
393///
394/// [`std::thread::LocalKey`]: crate::thread::LocalKey
395#[macro_export]
396#[stable(feature = "rust1", since = "1.0.0")]
397#[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")]
398#[allow_internal_unstable(thread_local_internals)]
399macro_rules! thread_local {
400    () => {};
401
402    ($($tt:tt)+) => {
403        $crate::thread::local_impl::thread_local_process_attrs!([] []; $($tt)+);
404    };
405}
406
407/// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
408#[stable(feature = "thread_local_try_with", since = "1.26.0")]
409#[non_exhaustive]
410#[derive(Clone, Copy, Eq, PartialEq)]
411pub struct AccessError;
412
413#[stable(feature = "thread_local_try_with", since = "1.26.0")]
414impl fmt::Debug for AccessError {
415    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
416        f.debug_struct("AccessError").finish()
417    }
418}
419
420#[stable(feature = "thread_local_try_with", since = "1.26.0")]
421impl fmt::Display for AccessError {
422    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
423        fmt::Display::fmt("already destroyed", f)
424    }
425}
426
427#[stable(feature = "thread_local_try_with", since = "1.26.0")]
428impl Error for AccessError {}
429
430// This ensures the panicking code is outlined from `with` for `LocalKey`.
431#[cfg_attr(feature = "ferrocene_certified_runtime", expect(unused_variables))]
432#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
433#[track_caller]
434#[cold]
435fn panic_access_error(err: AccessError) -> ! {
436    panic!("cannot access a Thread Local Storage value during or after destruction: {err:?}")
437}
438
439impl<T: 'static> LocalKey<T> {
440    #[doc(hidden)]
441    #[unstable(
442        feature = "thread_local_internals",
443        reason = "recently added to create a key",
444        issue = "none"
445    )]
446    pub const unsafe fn new(inner: fn(Option<&mut Option<T>>) -> *const T) -> LocalKey<T> {
447        LocalKey { inner }
448    }
449
450    /// Acquires a reference to the value in this TLS key.
451    ///
452    /// This will lazily initialize the value if this thread has not referenced
453    /// this key yet.
454    ///
455    /// # Panics
456    ///
457    /// This function will `panic!()` if the key currently has its
458    /// destructor running, and it **may** panic if the destructor has
459    /// previously been run for this thread.
460    ///
461    /// # Examples
462    ///
463    /// ```
464    /// thread_local! {
465    ///     pub static STATIC: String = String::from("I am");
466    /// }
467    ///
468    /// assert_eq!(
469    ///     STATIC.with(|original_value| format!("{original_value} initialized")),
470    ///     "I am initialized",
471    /// );
472    /// ```
473    #[stable(feature = "rust1", since = "1.0.0")]
474    pub fn with<F, R>(&'static self, f: F) -> R
475    where
476        F: FnOnce(&T) -> R,
477    {
478        match self.try_with(f) {
479            Ok(r) => r,
480            Err(err) => panic_access_error(err),
481        }
482    }
483
484    /// Acquires a reference to the value in this TLS key.
485    ///
486    /// This will lazily initialize the value if this thread has not referenced
487    /// this key yet. If the key has been destroyed (which may happen if this is called
488    /// in a destructor), this function will return an [`AccessError`].
489    ///
490    /// # Panics
491    ///
492    /// This function will still `panic!()` if the key is uninitialized and the
493    /// key's initializer panics.
494    ///
495    /// # Examples
496    ///
497    /// ```
498    /// thread_local! {
499    ///     pub static STATIC: String = String::from("I am");
500    /// }
501    ///
502    /// assert_eq!(
503    ///     STATIC.try_with(|original_value| format!("{original_value} initialized")),
504    ///     Ok(String::from("I am initialized")),
505    /// );
506    /// ```
507    #[stable(feature = "thread_local_try_with", since = "1.26.0")]
508    #[inline]
509    pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
510    where
511        F: FnOnce(&T) -> R,
512    {
513        let thread_local = unsafe { (self.inner)(None).as_ref().ok_or(AccessError)? };
514        Ok(f(thread_local))
515    }
516
517    /// Acquires a reference to the value in this TLS key, initializing it with
518    /// `init` if it wasn't already initialized on this thread.
519    ///
520    /// If `init` was used to initialize the thread local variable, `None` is
521    /// passed as the first argument to `f`. If it was already initialized,
522    /// `Some(init)` is passed to `f`.
523    ///
524    /// # Panics
525    ///
526    /// This function will panic if the key currently has its destructor
527    /// running, and it **may** panic if the destructor has previously been run
528    /// for this thread.
529    fn initialize_with<F, R>(&'static self, init: T, f: F) -> R
530    where
531        F: FnOnce(Option<T>, &T) -> R,
532    {
533        let mut init = Some(init);
534
535        let reference = unsafe {
536            match (self.inner)(Some(&mut init)).as_ref() {
537                Some(r) => r,
538                None => panic_access_error(AccessError),
539            }
540        };
541
542        f(init, reference)
543    }
544}
545
546impl<T: 'static> LocalKey<Cell<T>> {
547    /// Sets or initializes the contained value.
548    ///
549    /// Unlike the other methods, this will *not* run the lazy initializer of
550    /// the thread local. Instead, it will be directly initialized with the
551    /// given value if it wasn't initialized yet.
552    ///
553    /// # Panics
554    ///
555    /// Panics if the key currently has its destructor running,
556    /// and it **may** panic if the destructor has previously been run for this thread.
557    ///
558    /// # Examples
559    ///
560    /// ```
561    /// use std::cell::Cell;
562    ///
563    /// thread_local! {
564    ///     static X: Cell<i32> = panic!("!");
565    /// }
566    ///
567    /// // Calling X.get() here would result in a panic.
568    ///
569    /// X.set(123); // But X.set() is fine, as it skips the initializer above.
570    ///
571    /// assert_eq!(X.get(), 123);
572    /// ```
573    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
574    pub fn set(&'static self, value: T) {
575        self.initialize_with(Cell::new(value), |value, cell| {
576            if let Some(value) = value {
577                // The cell was already initialized, so `value` wasn't used to
578                // initialize it. So we overwrite the current value with the
579                // new one instead.
580                cell.set(value.into_inner());
581            }
582        });
583    }
584
585    /// Returns a copy of the contained value.
586    ///
587    /// This will lazily initialize the value if this thread has not referenced
588    /// this key yet.
589    ///
590    /// # Panics
591    ///
592    /// Panics if the key currently has its destructor running,
593    /// and it **may** panic if the destructor has previously been run for this thread.
594    ///
595    /// # Examples
596    ///
597    /// ```
598    /// use std::cell::Cell;
599    ///
600    /// thread_local! {
601    ///     static X: Cell<i32> = const { Cell::new(1) };
602    /// }
603    ///
604    /// assert_eq!(X.get(), 1);
605    /// ```
606    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
607    pub fn get(&'static self) -> T
608    where
609        T: Copy,
610    {
611        self.with(Cell::get)
612    }
613
614    /// Takes the contained value, leaving `Default::default()` in its place.
615    ///
616    /// This will lazily initialize the value if this thread has not referenced
617    /// this key yet.
618    ///
619    /// # Panics
620    ///
621    /// Panics if the key currently has its destructor running,
622    /// and it **may** panic if the destructor has previously been run for this thread.
623    ///
624    /// # Examples
625    ///
626    /// ```
627    /// use std::cell::Cell;
628    ///
629    /// thread_local! {
630    ///     static X: Cell<Option<i32>> = const { Cell::new(Some(1)) };
631    /// }
632    ///
633    /// assert_eq!(X.take(), Some(1));
634    /// assert_eq!(X.take(), None);
635    /// ```
636    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
637    pub fn take(&'static self) -> T
638    where
639        T: Default,
640    {
641        self.with(Cell::take)
642    }
643
644    /// Replaces the contained value, returning the old value.
645    ///
646    /// This will lazily initialize the value if this thread has not referenced
647    /// this key yet.
648    ///
649    /// # Panics
650    ///
651    /// Panics if the key currently has its destructor running,
652    /// and it **may** panic if the destructor has previously been run for this thread.
653    ///
654    /// # Examples
655    ///
656    /// ```
657    /// use std::cell::Cell;
658    ///
659    /// thread_local! {
660    ///     static X: Cell<i32> = const { Cell::new(1) };
661    /// }
662    ///
663    /// assert_eq!(X.replace(2), 1);
664    /// assert_eq!(X.replace(3), 2);
665    /// ```
666    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
667    #[rustc_confusables("swap")]
668    pub fn replace(&'static self, value: T) -> T {
669        self.with(|cell| cell.replace(value))
670    }
671
672    /// Updates the contained value using a function.
673    ///
674    /// # Examples
675    ///
676    /// ```
677    /// #![feature(local_key_cell_update)]
678    /// use std::cell::Cell;
679    ///
680    /// thread_local! {
681    ///     static X: Cell<i32> = const { Cell::new(5) };
682    /// }
683    ///
684    /// X.update(|x| x + 1);
685    /// assert_eq!(X.get(), 6);
686    /// ```
687    #[unstable(feature = "local_key_cell_update", issue = "143989")]
688    pub fn update(&'static self, f: impl FnOnce(T) -> T)
689    where
690        T: Copy,
691    {
692        self.with(|cell| cell.update(f))
693    }
694}
695
696impl<T: 'static> LocalKey<RefCell<T>> {
697    /// Acquires a reference to the contained value.
698    ///
699    /// This will lazily initialize the value if this thread has not referenced
700    /// this key yet.
701    ///
702    /// # Panics
703    ///
704    /// Panics if the value is currently mutably borrowed.
705    ///
706    /// Panics if the key currently has its destructor running,
707    /// and it **may** panic if the destructor has previously been run for this thread.
708    ///
709    /// # Examples
710    ///
711    /// ```
712    /// use std::cell::RefCell;
713    ///
714    /// thread_local! {
715    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
716    /// }
717    ///
718    /// X.with_borrow(|v| assert!(v.is_empty()));
719    /// ```
720    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
721    pub fn with_borrow<F, R>(&'static self, f: F) -> R
722    where
723        F: FnOnce(&T) -> R,
724    {
725        self.with(|cell| f(&cell.borrow()))
726    }
727
728    /// Acquires a mutable reference to the contained value.
729    ///
730    /// This will lazily initialize the value if this thread has not referenced
731    /// this key yet.
732    ///
733    /// # Panics
734    ///
735    /// Panics if the value is currently borrowed.
736    ///
737    /// Panics if the key currently has its destructor running,
738    /// and it **may** panic if the destructor has previously been run for this thread.
739    ///
740    /// # Examples
741    ///
742    /// ```
743    /// use std::cell::RefCell;
744    ///
745    /// thread_local! {
746    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
747    /// }
748    ///
749    /// X.with_borrow_mut(|v| v.push(1));
750    ///
751    /// X.with_borrow(|v| assert_eq!(*v, vec![1]));
752    /// ```
753    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
754    pub fn with_borrow_mut<F, R>(&'static self, f: F) -> R
755    where
756        F: FnOnce(&mut T) -> R,
757    {
758        self.with(|cell| f(&mut cell.borrow_mut()))
759    }
760
761    /// Sets or initializes the contained value.
762    ///
763    /// Unlike the other methods, this will *not* run the lazy initializer of
764    /// the thread local. Instead, it will be directly initialized with the
765    /// given value if it wasn't initialized yet.
766    ///
767    /// # Panics
768    ///
769    /// Panics if the value is currently borrowed.
770    ///
771    /// Panics if the key currently has its destructor running,
772    /// and it **may** panic if the destructor has previously been run for this thread.
773    ///
774    /// # Examples
775    ///
776    /// ```
777    /// use std::cell::RefCell;
778    ///
779    /// thread_local! {
780    ///     static X: RefCell<Vec<i32>> = panic!("!");
781    /// }
782    ///
783    /// // Calling X.with() here would result in a panic.
784    ///
785    /// X.set(vec![1, 2, 3]); // But X.set() is fine, as it skips the initializer above.
786    ///
787    /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
788    /// ```
789    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
790    pub fn set(&'static self, value: T) {
791        self.initialize_with(RefCell::new(value), |value, cell| {
792            if let Some(value) = value {
793                // The cell was already initialized, so `value` wasn't used to
794                // initialize it. So we overwrite the current value with the
795                // new one instead.
796                *cell.borrow_mut() = value.into_inner();
797            }
798        });
799    }
800
801    /// Takes the contained value, leaving `Default::default()` in its place.
802    ///
803    /// This will lazily initialize the value if this thread has not referenced
804    /// this key yet.
805    ///
806    /// # Panics
807    ///
808    /// Panics if the value is currently borrowed.
809    ///
810    /// Panics if the key currently has its destructor running,
811    /// and it **may** panic if the destructor has previously been run for this thread.
812    ///
813    /// # Examples
814    ///
815    /// ```
816    /// use std::cell::RefCell;
817    ///
818    /// thread_local! {
819    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
820    /// }
821    ///
822    /// X.with_borrow_mut(|v| v.push(1));
823    ///
824    /// let a = X.take();
825    ///
826    /// assert_eq!(a, vec![1]);
827    ///
828    /// X.with_borrow(|v| assert!(v.is_empty()));
829    /// ```
830    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
831    pub fn take(&'static self) -> T
832    where
833        T: Default,
834    {
835        self.with(RefCell::take)
836    }
837
838    /// Replaces the contained value, returning the old value.
839    ///
840    /// # Panics
841    ///
842    /// Panics if the value is currently borrowed.
843    ///
844    /// Panics if the key currently has its destructor running,
845    /// and it **may** panic if the destructor has previously been run for this thread.
846    ///
847    /// # Examples
848    ///
849    /// ```
850    /// use std::cell::RefCell;
851    ///
852    /// thread_local! {
853    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
854    /// }
855    ///
856    /// let prev = X.replace(vec![1, 2, 3]);
857    /// assert!(prev.is_empty());
858    ///
859    /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
860    /// ```
861    #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
862    #[rustc_confusables("swap")]
863    pub fn replace(&'static self, value: T) -> T {
864        self.with(|cell| cell.replace(value))
865    }
866}