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}