]> git.lizzy.rs Git - rust.git/blob - library/std/src/thread/local.rs
Rollup merge of #97336 - tshepang:typo, r=cjgillot
[rust.git] / library / std / src / thread / local.rs
1 //! Thread local storage
2
3 #![unstable(feature = "thread_local_internals", issue = "none")]
4
5 #[cfg(all(test, not(target_os = "emscripten")))]
6 mod tests;
7
8 #[cfg(test)]
9 mod dynamic_tests;
10
11 use crate::cell::{Cell, RefCell};
12 use crate::error::Error;
13 use crate::fmt;
14
15 /// A thread local storage key which owns its contents.
16 ///
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.
20 ///
21 /// The [`with`] method yields a reference to the contained value which cannot be
22 /// sent across threads or escape the given closure.
23 ///
24 /// [`thread_local!`]: crate::thread_local
25 ///
26 /// # Initialization and Destruction
27 ///
28 /// Initialization is dynamically performed on the first call to [`with`]
29 /// within a thread, and values that implement [`Drop`] get destructed when a
30 /// thread exits. Some caveats apply, which are explained below.
31 ///
32 /// A `LocalKey`'s initializer cannot recursively depend on itself, and using
33 /// a `LocalKey` in this way will cause the initializer to infinitely recurse
34 /// on the first call to `with`.
35 ///
36 /// # Examples
37 ///
38 /// ```
39 /// use std::cell::RefCell;
40 /// use std::thread;
41 ///
42 /// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
43 ///
44 /// FOO.with(|f| {
45 ///     assert_eq!(*f.borrow(), 1);
46 ///     *f.borrow_mut() = 2;
47 /// });
48 ///
49 /// // each thread starts out with the initial value of 1
50 /// let t = thread::spawn(move|| {
51 ///     FOO.with(|f| {
52 ///         assert_eq!(*f.borrow(), 1);
53 ///         *f.borrow_mut() = 3;
54 ///     });
55 /// });
56 ///
57 /// // wait for the thread to complete and bail out on panic
58 /// t.join().unwrap();
59 ///
60 /// // we retain our original value of 2 despite the child thread
61 /// FOO.with(|f| {
62 ///     assert_eq!(*f.borrow(), 2);
63 /// });
64 /// ```
65 ///
66 /// # Platform-specific behavior
67 ///
68 /// Note that a "best effort" is made to ensure that destructors for types
69 /// stored in thread local storage are run, but not all platforms can guarantee
70 /// that destructors will be run for all types in thread local storage. For
71 /// example, there are a number of known caveats where destructors are not run:
72 ///
73 /// 1. On Unix systems when pthread-based TLS is being used, destructors will
74 ///    not be run for TLS values on the main thread when it exits. Note that the
75 ///    application will exit immediately after the main thread exits as well.
76 /// 2. On all platforms it's possible for TLS to re-initialize other TLS slots
77 ///    during destruction. Some platforms ensure that this cannot happen
78 ///    infinitely by preventing re-initialization of any slot that has been
79 ///    destroyed, but not all platforms have this guard. Those platforms that do
80 ///    not guard typically have a synthetic limit after which point no more
81 ///    destructors are run.
82 /// 3. When the process exits on Windows systems, TLS destructors may only be
83 ///    run on the thread that causes the process to exit. This is because the
84 ///    other threads may be forcibly terminated.
85 ///
86 /// ## Synchronization in thread-local destructors
87 ///
88 /// On Windows, synchronization operations (such as [`JoinHandle::join`]) in
89 /// thread local destructors are prone to deadlocks and so should be avoided.
90 /// This is because the [loader lock] is held while a destructor is run. The
91 /// lock is acquired whenever a thread starts or exits or when a DLL is loaded
92 /// or unloaded. Therefore these events are blocked for as long as a thread
93 /// local destructor is running.
94 ///
95 /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
96 /// [`JoinHandle::join`]: crate::thread::JoinHandle::join
97 /// [`with`]: LocalKey::with
98 #[stable(feature = "rust1", since = "1.0.0")]
99 pub struct LocalKey<T: 'static> {
100     // This outer `LocalKey<T>` type is what's going to be stored in statics,
101     // but actual data inside will sometimes be tagged with #[thread_local].
102     // It's not valid for a true static to reference a #[thread_local] static,
103     // so we get around that by exposing an accessor through a layer of function
104     // indirection (this thunk).
105     //
106     // Note that the thunk is itself unsafe because the returned lifetime of the
107     // slot where data lives, `'static`, is not actually valid. The lifetime
108     // here is actually slightly shorter than the currently running thread!
109     //
110     // Although this is an extra layer of indirection, it should in theory be
111     // trivially devirtualizable by LLVM because the value of `inner` never
112     // changes and the constant should be readonly within a crate. This mainly
113     // only runs into problems when TLS statics are exported across crates.
114     inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>,
115 }
116
117 #[stable(feature = "std_debug", since = "1.16.0")]
118 impl<T: 'static> fmt::Debug for LocalKey<T> {
119     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120         f.debug_struct("LocalKey").finish_non_exhaustive()
121     }
122 }
123
124 /// Declare a new thread local storage key of type [`std::thread::LocalKey`].
125 ///
126 /// # Syntax
127 ///
128 /// The macro wraps any number of static declarations and makes them thread local.
129 /// Publicity and attributes for each static are allowed. Example:
130 ///
131 /// ```
132 /// use std::cell::RefCell;
133 /// thread_local! {
134 ///     pub static FOO: RefCell<u32> = RefCell::new(1);
135 ///
136 ///     #[allow(unused)]
137 ///     static BAR: RefCell<f32> = RefCell::new(1.0);
138 /// }
139 /// # fn main() {}
140 /// ```
141 ///
142 /// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
143 /// information.
144 ///
145 /// [`std::thread::LocalKey`]: crate::thread::LocalKey
146 #[macro_export]
147 #[stable(feature = "rust1", since = "1.0.0")]
148 #[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")]
149 #[allow_internal_unstable(thread_local_internals)]
150 macro_rules! thread_local {
151     // empty (base case for the recursion)
152     () => {};
153
154     ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => (
155         $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
156         $crate::thread_local!($($rest)*);
157     );
158
159     ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => (
160         $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
161     );
162
163     // process multiple declarations
164     ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
165         $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
166         $crate::thread_local!($($rest)*);
167     );
168
169     // handle a single declaration
170     ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
171         $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
172     );
173 }
174
175 #[doc(hidden)]
176 #[unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")]
177 #[macro_export]
178 #[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
179 #[allow_internal_unsafe]
180 macro_rules! __thread_local_inner {
181     // used to generate the `LocalKey` value for const-initialized thread locals
182     (@key $t:ty, const $init:expr) => {{
183         #[cfg_attr(not(windows), inline)] // see comments below
184         #[deny(unsafe_op_in_unsafe_fn)]
185         unsafe fn __getit(
186             _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
187         ) -> $crate::option::Option<&'static $t> {
188             const INIT_EXPR: $t = $init;
189
190             // wasm without atomics maps directly to `static mut`, and dtors
191             // aren't implemented because thread dtors aren't really a thing
192             // on wasm right now
193             //
194             // FIXME(#84224) this should come after the `target_thread_local`
195             // block.
196             #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
197             {
198                 static mut VAL: $t = INIT_EXPR;
199                 unsafe { $crate::option::Option::Some(&VAL) }
200             }
201
202             // If the platform has support for `#[thread_local]`, use it.
203             #[cfg(all(
204                 target_thread_local,
205                 not(all(target_family = "wasm", not(target_feature = "atomics"))),
206             ))]
207             {
208                 #[thread_local]
209                 static mut VAL: $t = INIT_EXPR;
210
211                 // If a dtor isn't needed we can do something "very raw" and
212                 // just get going.
213                 if !$crate::mem::needs_drop::<$t>() {
214                     unsafe {
215                         return $crate::option::Option::Some(&VAL)
216                     }
217                 }
218
219                 // 0 == dtor not registered
220                 // 1 == dtor registered, dtor not run
221                 // 2 == dtor registered and is running or has run
222                 #[thread_local]
223                 static mut STATE: $crate::primitive::u8 = 0;
224
225                 unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) {
226                     let ptr = ptr as *mut $t;
227
228                     unsafe {
229                         $crate::debug_assert_eq!(STATE, 1);
230                         STATE = 2;
231                         $crate::ptr::drop_in_place(ptr);
232                     }
233                 }
234
235                 unsafe {
236                     match STATE {
237                         // 0 == we haven't registered a destructor, so do
238                         //   so now.
239                         0 => {
240                             $crate::thread::__FastLocalKeyInner::<$t>::register_dtor(
241                                 $crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8,
242                                 destroy,
243                             );
244                             STATE = 1;
245                             $crate::option::Option::Some(&VAL)
246                         }
247                         // 1 == the destructor is registered and the value
248                         //   is valid, so return the pointer.
249                         1 => $crate::option::Option::Some(&VAL),
250                         // otherwise the destructor has already run, so we
251                         // can't give access.
252                         _ => $crate::option::Option::None,
253                     }
254                 }
255             }
256
257             // On platforms without `#[thread_local]` we fall back to the
258             // same implementation as below for os thread locals.
259             #[cfg(all(
260                 not(target_thread_local),
261                 not(all(target_family = "wasm", not(target_feature = "atomics"))),
262             ))]
263             {
264                 #[inline]
265                 const fn __init() -> $t { INIT_EXPR }
266                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
267                     $crate::thread::__OsLocalKeyInner::new();
268                 #[allow(unused_unsafe)]
269                 unsafe {
270                     __KEY.get(move || {
271                         if let $crate::option::Option::Some(init) = _init {
272                             if let $crate::option::Option::Some(value) = init.take() {
273                                 return value;
274                             } else if $crate::cfg!(debug_assertions) {
275                                 $crate::unreachable!("missing initial value");
276                             }
277                         }
278                         __init()
279                     })
280                 }
281             }
282         }
283
284         unsafe {
285             $crate::thread::LocalKey::new(__getit)
286         }
287     }};
288
289     // used to generate the `LocalKey` value for `thread_local!`
290     (@key $t:ty, $init:expr) => {
291         {
292             #[inline]
293             fn __init() -> $t { $init }
294
295             // When reading this function you might ask "why is this inlined
296             // everywhere other than Windows?", and that's a very reasonable
297             // question to ask. The short story is that it segfaults rustc if
298             // this function is inlined. The longer story is that Windows looks
299             // to not support `extern` references to thread locals across DLL
300             // boundaries. This appears to at least not be supported in the ABI
301             // that LLVM implements.
302             //
303             // Because of this we never inline on Windows, but we do inline on
304             // other platforms (where external references to thread locals
305             // across DLLs are supported). A better fix for this would be to
306             // inline this function on Windows, but only for "statically linked"
307             // components. For example if two separately compiled rlibs end up
308             // getting linked into a DLL then it's fine to inline this function
309             // across that boundary. It's only not fine to inline this function
310             // across a DLL boundary. Unfortunately rustc doesn't currently
311             // have this sort of logic available in an attribute, and it's not
312             // clear that rustc is even equipped to answer this (it's more of a
313             // Cargo question kinda). This means that, unfortunately, Windows
314             // gets the pessimistic path for now where it's never inlined.
315             //
316             // The issue of "should enable on Windows sometimes" is #84933
317             #[cfg_attr(not(windows), inline)]
318             unsafe fn __getit(
319                 init: $crate::option::Option<&mut $crate::option::Option<$t>>,
320             ) -> $crate::option::Option<&'static $t> {
321                 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
322                 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
323                     $crate::thread::__StaticLocalKeyInner::new();
324
325                 #[thread_local]
326                 #[cfg(all(
327                     target_thread_local,
328                     not(all(target_family = "wasm", not(target_feature = "atomics"))),
329                 ))]
330                 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
331                     $crate::thread::__FastLocalKeyInner::new();
332
333                 #[cfg(all(
334                     not(target_thread_local),
335                     not(all(target_family = "wasm", not(target_feature = "atomics"))),
336                 ))]
337                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
338                     $crate::thread::__OsLocalKeyInner::new();
339
340                 // FIXME: remove the #[allow(...)] marker when macros don't
341                 // raise warning for missing/extraneous unsafe blocks anymore.
342                 // See https://github.com/rust-lang/rust/issues/74838.
343                 #[allow(unused_unsafe)]
344                 unsafe {
345                     __KEY.get(move || {
346                         if let $crate::option::Option::Some(init) = init {
347                             if let $crate::option::Option::Some(value) = init.take() {
348                                 return value;
349                             } else if $crate::cfg!(debug_assertions) {
350                                 $crate::unreachable!("missing default value");
351                             }
352                         }
353                         __init()
354                     })
355                 }
356             }
357
358             unsafe {
359                 $crate::thread::LocalKey::new(__getit)
360             }
361         }
362     };
363     ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
364         $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
365             $crate::__thread_local_inner!(@key $t, $($init)*);
366     }
367 }
368
369 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
370 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
371 #[non_exhaustive]
372 #[derive(Clone, Copy, Eq, PartialEq)]
373 pub struct AccessError;
374
375 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
376 impl fmt::Debug for AccessError {
377     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378         f.debug_struct("AccessError").finish()
379     }
380 }
381
382 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
383 impl fmt::Display for AccessError {
384     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385         fmt::Display::fmt("already destroyed", f)
386     }
387 }
388
389 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
390 impl Error for AccessError {}
391
392 impl<T: 'static> LocalKey<T> {
393     #[doc(hidden)]
394     #[unstable(
395         feature = "thread_local_internals",
396         reason = "recently added to create a key",
397         issue = "none"
398     )]
399     #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
400     pub const unsafe fn new(
401         inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>,
402     ) -> LocalKey<T> {
403         LocalKey { inner }
404     }
405
406     /// Acquires a reference to the value in this TLS key.
407     ///
408     /// This will lazily initialize the value if this thread has not referenced
409     /// this key yet.
410     ///
411     /// # Panics
412     ///
413     /// This function will `panic!()` if the key currently has its
414     /// destructor running, and it **may** panic if the destructor has
415     /// previously been run for this thread.
416     #[stable(feature = "rust1", since = "1.0.0")]
417     pub fn with<F, R>(&'static self, f: F) -> R
418     where
419         F: FnOnce(&T) -> R,
420     {
421         self.try_with(f).expect(
422             "cannot access a Thread Local Storage value \
423              during or after destruction",
424         )
425     }
426
427     /// Acquires a reference to the value in this TLS key.
428     ///
429     /// This will lazily initialize the value if this thread has not referenced
430     /// this key yet. If the key has been destroyed (which may happen if this is called
431     /// in a destructor), this function will return an [`AccessError`].
432     ///
433     /// # Panics
434     ///
435     /// This function will still `panic!()` if the key is uninitialized and the
436     /// key's initializer panics.
437     #[stable(feature = "thread_local_try_with", since = "1.26.0")]
438     #[inline]
439     pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
440     where
441         F: FnOnce(&T) -> R,
442     {
443         unsafe {
444             let thread_local = (self.inner)(None).ok_or(AccessError)?;
445             Ok(f(thread_local))
446         }
447     }
448
449     /// Acquires a reference to the value in this TLS key, initializing it with
450     /// `init` if it wasn't already initialized on this thread.
451     ///
452     /// If `init` was used to initialize the thread local variable, `None` is
453     /// passed as the first argument to `f`. If it was already initialized,
454     /// `Some(init)` is passed to `f`.
455     ///
456     /// # Panics
457     ///
458     /// This function will panic if the key currently has its destructor
459     /// running, and it **may** panic if the destructor has previously been run
460     /// for this thread.
461     fn initialize_with<F, R>(&'static self, init: T, f: F) -> R
462     where
463         F: FnOnce(Option<T>, &T) -> R,
464     {
465         unsafe {
466             let mut init = Some(init);
467             let reference = (self.inner)(Some(&mut init)).expect(
468                 "cannot access a Thread Local Storage value \
469                  during or after destruction",
470             );
471             f(init, reference)
472         }
473     }
474 }
475
476 impl<T: 'static> LocalKey<Cell<T>> {
477     /// Sets or initializes the contained value.
478     ///
479     /// Unlike the other methods, this will *not* run the lazy initializer of
480     /// the thread local. Instead, it will be directly initialized with the
481     /// given value if it wasn't initialized yet.
482     ///
483     /// # Panics
484     ///
485     /// Panics if the key currently has its destructor running,
486     /// and it **may** panic if the destructor has previously been run for this thread.
487     ///
488     /// # Examples
489     ///
490     /// ```
491     /// #![feature(local_key_cell_methods)]
492     /// use std::cell::Cell;
493     ///
494     /// thread_local! {
495     ///     static X: Cell<i32> = panic!("!");
496     /// }
497     ///
498     /// // Calling X.get() here would result in a panic.
499     ///
500     /// X.set(123); // But X.set() is fine, as it skips the initializer above.
501     ///
502     /// assert_eq!(X.get(), 123);
503     /// ```
504     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
505     pub fn set(&'static self, value: T) {
506         self.initialize_with(Cell::new(value), |value, cell| {
507             if let Some(value) = value {
508                 // The cell was already initialized, so `value` wasn't used to
509                 // initialize it. So we overwrite the current value with the
510                 // new one instead.
511                 cell.set(value.into_inner());
512             }
513         });
514     }
515
516     /// Returns a copy of the contained value.
517     ///
518     /// This will lazily initialize the value if this thread has not referenced
519     /// this key yet.
520     ///
521     /// # Panics
522     ///
523     /// Panics if the key currently has its destructor running,
524     /// and it **may** panic if the destructor has previously been run for this thread.
525     ///
526     /// # Examples
527     ///
528     /// ```
529     /// #![feature(local_key_cell_methods)]
530     /// use std::cell::Cell;
531     ///
532     /// thread_local! {
533     ///     static X: Cell<i32> = Cell::new(1);
534     /// }
535     ///
536     /// assert_eq!(X.get(), 1);
537     /// ```
538     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
539     pub fn get(&'static self) -> T
540     where
541         T: Copy,
542     {
543         self.with(|cell| cell.get())
544     }
545
546     /// Takes the contained value, leaving `Default::default()` in its place.
547     ///
548     /// This will lazily initialize the value if this thread has not referenced
549     /// this key yet.
550     ///
551     /// # Panics
552     ///
553     /// Panics if the key currently has its destructor running,
554     /// and it **may** panic if the destructor has previously been run for this thread.
555     ///
556     /// # Examples
557     ///
558     /// ```
559     /// #![feature(local_key_cell_methods)]
560     /// use std::cell::Cell;
561     ///
562     /// thread_local! {
563     ///     static X: Cell<Option<i32>> = Cell::new(Some(1));
564     /// }
565     ///
566     /// assert_eq!(X.take(), Some(1));
567     /// assert_eq!(X.take(), None);
568     /// ```
569     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
570     pub fn take(&'static self) -> T
571     where
572         T: Default,
573     {
574         self.with(|cell| cell.take())
575     }
576
577     /// Replaces the contained value, returning the old value.
578     ///
579     /// This will lazily initialize the value if this thread has not referenced
580     /// this key yet.
581     ///
582     /// # Panics
583     ///
584     /// Panics if the key currently has its destructor running,
585     /// and it **may** panic if the destructor has previously been run for this thread.
586     ///
587     /// # Examples
588     ///
589     /// ```
590     /// #![feature(local_key_cell_methods)]
591     /// use std::cell::Cell;
592     ///
593     /// thread_local! {
594     ///     static X: Cell<i32> = Cell::new(1);
595     /// }
596     ///
597     /// assert_eq!(X.replace(2), 1);
598     /// assert_eq!(X.replace(3), 2);
599     /// ```
600     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
601     pub fn replace(&'static self, value: T) -> T {
602         self.with(|cell| cell.replace(value))
603     }
604 }
605
606 impl<T: 'static> LocalKey<RefCell<T>> {
607     /// Acquires a reference to the contained value.
608     ///
609     /// This will lazily initialize the value if this thread has not referenced
610     /// this key yet.
611     ///
612     /// # Panics
613     ///
614     /// Panics if the value is currently mutably borrowed.
615     ///
616     /// Panics if the key currently has its destructor running,
617     /// and it **may** panic if the destructor has previously been run for this thread.
618     ///
619     /// # Example
620     ///
621     /// ```
622     /// #![feature(local_key_cell_methods)]
623     /// use std::cell::RefCell;
624     ///
625     /// thread_local! {
626     ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
627     /// }
628     ///
629     /// X.with_borrow(|v| assert!(v.is_empty()));
630     /// ```
631     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
632     pub fn with_borrow<F, R>(&'static self, f: F) -> R
633     where
634         F: FnOnce(&T) -> R,
635     {
636         self.with(|cell| f(&cell.borrow()))
637     }
638
639     /// Acquires a mutable reference to the contained value.
640     ///
641     /// This will lazily initialize the value if this thread has not referenced
642     /// this key yet.
643     ///
644     /// # Panics
645     ///
646     /// Panics if the value is currently borrowed.
647     ///
648     /// Panics if the key currently has its destructor running,
649     /// and it **may** panic if the destructor has previously been run for this thread.
650     ///
651     /// # Example
652     ///
653     /// ```
654     /// #![feature(local_key_cell_methods)]
655     /// use std::cell::RefCell;
656     ///
657     /// thread_local! {
658     ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
659     /// }
660     ///
661     /// X.with_borrow_mut(|v| v.push(1));
662     ///
663     /// X.with_borrow(|v| assert_eq!(*v, vec![1]));
664     /// ```
665     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
666     pub fn with_borrow_mut<F, R>(&'static self, f: F) -> R
667     where
668         F: FnOnce(&mut T) -> R,
669     {
670         self.with(|cell| f(&mut cell.borrow_mut()))
671     }
672
673     /// Sets or initializes the contained value.
674     ///
675     /// Unlike the other methods, this will *not* run the lazy initializer of
676     /// the thread local. Instead, it will be directly initialized with the
677     /// given value if it wasn't initialized yet.
678     ///
679     /// # Panics
680     ///
681     /// Panics if the value is currently borrowed.
682     ///
683     /// Panics if the key currently has its destructor running,
684     /// and it **may** panic if the destructor has previously been run for this thread.
685     ///
686     /// # Examples
687     ///
688     /// ```
689     /// #![feature(local_key_cell_methods)]
690     /// use std::cell::RefCell;
691     ///
692     /// thread_local! {
693     ///     static X: RefCell<Vec<i32>> = panic!("!");
694     /// }
695     ///
696     /// // Calling X.with() here would result in a panic.
697     ///
698     /// X.set(vec![1, 2, 3]); // But X.set() is fine, as it skips the initializer above.
699     ///
700     /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
701     /// ```
702     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
703     pub fn set(&'static self, value: T) {
704         self.initialize_with(RefCell::new(value), |value, cell| {
705             if let Some(value) = value {
706                 // The cell was already initialized, so `value` wasn't used to
707                 // initialize it. So we overwrite the current value with the
708                 // new one instead.
709                 *cell.borrow_mut() = value.into_inner();
710             }
711         });
712     }
713
714     /// Takes the contained value, leaving `Default::default()` in its place.
715     ///
716     /// This will lazily initialize the value if this thread has not referenced
717     /// this key yet.
718     ///
719     /// # Panics
720     ///
721     /// Panics if the value is currently borrowed.
722     ///
723     /// Panics if the key currently has its destructor running,
724     /// and it **may** panic if the destructor has previously been run for this thread.
725     ///
726     /// # Examples
727     ///
728     /// ```
729     /// #![feature(local_key_cell_methods)]
730     /// use std::cell::RefCell;
731     ///
732     /// thread_local! {
733     ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
734     /// }
735     ///
736     /// X.with_borrow_mut(|v| v.push(1));
737     ///
738     /// let a = X.take();
739     ///
740     /// assert_eq!(a, vec![1]);
741     ///
742     /// X.with_borrow(|v| assert!(v.is_empty()));
743     /// ```
744     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
745     pub fn take(&'static self) -> T
746     where
747         T: Default,
748     {
749         self.with(|cell| cell.take())
750     }
751
752     /// Replaces the contained value, returning the old value.
753     ///
754     /// # Panics
755     ///
756     /// Panics if the value is currently borrowed.
757     ///
758     /// Panics if the key currently has its destructor running,
759     /// and it **may** panic if the destructor has previously been run for this thread.
760     ///
761     /// # Examples
762     ///
763     /// ```
764     /// #![feature(local_key_cell_methods)]
765     /// use std::cell::RefCell;
766     ///
767     /// thread_local! {
768     ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
769     /// }
770     ///
771     /// let prev = X.replace(vec![1, 2, 3]);
772     /// assert!(prev.is_empty());
773     ///
774     /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
775     /// ```
776     #[unstable(feature = "local_key_cell_methods", issue = "92122")]
777     pub fn replace(&'static self, value: T) -> T {
778         self.with(|cell| cell.replace(value))
779     }
780 }
781
782 mod lazy {
783     use crate::cell::UnsafeCell;
784     use crate::hint;
785     use crate::mem;
786
787     pub struct LazyKeyInner<T> {
788         inner: UnsafeCell<Option<T>>,
789     }
790
791     impl<T> LazyKeyInner<T> {
792         pub const fn new() -> LazyKeyInner<T> {
793             LazyKeyInner { inner: UnsafeCell::new(None) }
794         }
795
796         pub unsafe fn get(&self) -> Option<&'static T> {
797             // SAFETY: The caller must ensure no reference is ever handed out to
798             // the inner cell nor mutable reference to the Option<T> inside said
799             // cell. This make it safe to hand a reference, though the lifetime
800             // of 'static is itself unsafe, making the get method unsafe.
801             unsafe { (*self.inner.get()).as_ref() }
802         }
803
804         /// The caller must ensure that no reference is active: this method
805         /// needs unique access.
806         pub unsafe fn initialize<F: FnOnce() -> T>(&self, init: F) -> &'static T {
807             // Execute the initialization up front, *then* move it into our slot,
808             // just in case initialization fails.
809             let value = init();
810             let ptr = self.inner.get();
811
812             // SAFETY:
813             //
814             // note that this can in theory just be `*ptr = Some(value)`, but due to
815             // the compiler will currently codegen that pattern with something like:
816             //
817             //      ptr::drop_in_place(ptr)
818             //      ptr::write(ptr, Some(value))
819             //
820             // Due to this pattern it's possible for the destructor of the value in
821             // `ptr` (e.g., if this is being recursively initialized) to re-access
822             // TLS, in which case there will be a `&` and `&mut` pointer to the same
823             // value (an aliasing violation). To avoid setting the "I'm running a
824             // destructor" flag we just use `mem::replace` which should sequence the
825             // operations a little differently and make this safe to call.
826             //
827             // The precondition also ensures that we are the only one accessing
828             // `self` at the moment so replacing is fine.
829             unsafe {
830                 let _ = mem::replace(&mut *ptr, Some(value));
831             }
832
833             // SAFETY: With the call to `mem::replace` it is guaranteed there is
834             // a `Some` behind `ptr`, not a `None` so `unreachable_unchecked`
835             // will never be reached.
836             unsafe {
837                 // After storing `Some` we want to get a reference to the contents of
838                 // what we just stored. While we could use `unwrap` here and it should
839                 // always work it empirically doesn't seem to always get optimized away,
840                 // which means that using something like `try_with` can pull in
841                 // panicking code and cause a large size bloat.
842                 match *ptr {
843                     Some(ref x) => x,
844                     None => hint::unreachable_unchecked(),
845                 }
846             }
847         }
848
849         /// The other methods hand out references while taking &self.
850         /// As such, callers of this method must ensure no `&` and `&mut` are
851         /// available and used at the same time.
852         #[allow(unused)]
853         pub unsafe fn take(&mut self) -> Option<T> {
854             // SAFETY: See doc comment for this method.
855             unsafe { (*self.inner.get()).take() }
856         }
857     }
858 }
859
860 /// On some targets like wasm there's no threads, so no need to generate
861 /// thread locals and we can instead just use plain statics!
862 #[doc(hidden)]
863 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
864 pub mod statik {
865     use super::lazy::LazyKeyInner;
866     use crate::fmt;
867
868     pub struct Key<T> {
869         inner: LazyKeyInner<T>,
870     }
871
872     unsafe impl<T> Sync for Key<T> {}
873
874     impl<T> fmt::Debug for Key<T> {
875         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
876             f.debug_struct("Key").finish_non_exhaustive()
877         }
878     }
879
880     impl<T> Key<T> {
881         pub const fn new() -> Key<T> {
882             Key { inner: LazyKeyInner::new() }
883         }
884
885         pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> {
886             // SAFETY: The caller must ensure no reference is ever handed out to
887             // the inner cell nor mutable reference to the Option<T> inside said
888             // cell. This make it safe to hand a reference, though the lifetime
889             // of 'static is itself unsafe, making the get method unsafe.
890             let value = unsafe {
891                 match self.inner.get() {
892                     Some(ref value) => value,
893                     None => self.inner.initialize(init),
894                 }
895             };
896
897             Some(value)
898         }
899     }
900 }
901
902 #[doc(hidden)]
903 #[cfg(target_thread_local)]
904 pub mod fast {
905     use super::lazy::LazyKeyInner;
906     use crate::cell::Cell;
907     use crate::fmt;
908     use crate::mem;
909     use crate::sys::thread_local_dtor::register_dtor;
910
911     #[derive(Copy, Clone)]
912     enum DtorState {
913         Unregistered,
914         Registered,
915         RunningOrHasRun,
916     }
917
918     // This data structure has been carefully constructed so that the fast path
919     // only contains one branch on x86. That optimization is necessary to avoid
920     // duplicated tls lookups on OSX.
921     //
922     // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
923     pub struct Key<T> {
924         // If `LazyKeyInner::get` returns `None`, that indicates either:
925         //   * The value has never been initialized
926         //   * The value is being recursively initialized
927         //   * The value has already been destroyed or is being destroyed
928         // To determine which kind of `None`, check `dtor_state`.
929         //
930         // This is very optimizer friendly for the fast path - initialized but
931         // not yet dropped.
932         inner: LazyKeyInner<T>,
933
934         // Metadata to keep track of the state of the destructor. Remember that
935         // this variable is thread-local, not global.
936         dtor_state: Cell<DtorState>,
937     }
938
939     impl<T> fmt::Debug for Key<T> {
940         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
941             f.debug_struct("Key").finish_non_exhaustive()
942         }
943     }
944
945     impl<T> Key<T> {
946         pub const fn new() -> Key<T> {
947             Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }
948         }
949
950         // note that this is just a publicly-callable function only for the
951         // const-initialized form of thread locals, basically a way to call the
952         // free `register_dtor` function defined elsewhere in libstd.
953         pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
954             unsafe {
955                 register_dtor(a, dtor);
956             }
957         }
958
959         pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
960             // SAFETY: See the definitions of `LazyKeyInner::get` and
961             // `try_initialize` for more information.
962             //
963             // The caller must ensure no mutable references are ever active to
964             // the inner cell or the inner T when this is called.
965             // The `try_initialize` is dependant on the passed `init` function
966             // for this.
967             unsafe {
968                 match self.inner.get() {
969                     Some(val) => Some(val),
970                     None => self.try_initialize(init),
971                 }
972             }
973         }
974
975         // `try_initialize` is only called once per fast thread local variable,
976         // except in corner cases where thread_local dtors reference other
977         // thread_local's, or it is being recursively initialized.
978         //
979         // Macos: Inlining this function can cause two `tlv_get_addr` calls to
980         // be performed for every call to `Key::get`.
981         // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
982         #[inline(never)]
983         unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
984             // SAFETY: See comment above (this function doc).
985             if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } {
986                 // SAFETY: See comment above (this function doc).
987                 Some(unsafe { self.inner.initialize(init) })
988             } else {
989                 None
990             }
991         }
992
993         // `try_register_dtor` is only called once per fast thread local
994         // variable, except in corner cases where thread_local dtors reference
995         // other thread_local's, or it is being recursively initialized.
996         unsafe fn try_register_dtor(&self) -> bool {
997             match self.dtor_state.get() {
998                 DtorState::Unregistered => {
999                     // SAFETY: dtor registration happens before initialization.
1000                     // Passing `self` as a pointer while using `destroy_value<T>`
1001                     // is safe because the function will build a pointer to a
1002                     // Key<T>, which is the type of self and so find the correct
1003                     // size.
1004                     unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::<T>) };
1005                     self.dtor_state.set(DtorState::Registered);
1006                     true
1007                 }
1008                 DtorState::Registered => {
1009                     // recursively initialized
1010                     true
1011                 }
1012                 DtorState::RunningOrHasRun => false,
1013             }
1014         }
1015     }
1016
1017     unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) {
1018         let ptr = ptr as *mut Key<T>;
1019
1020         // SAFETY:
1021         //
1022         // The pointer `ptr` has been built just above and comes from
1023         // `try_register_dtor` where it is originally a Key<T> coming from `self`,
1024         // making it non-NUL and of the correct type.
1025         //
1026         // Right before we run the user destructor be sure to set the
1027         // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
1028         // causes future calls to `get` to run `try_initialize_drop` again,
1029         // which will now fail, and return `None`.
1030         unsafe {
1031             let value = (*ptr).inner.take();
1032             (*ptr).dtor_state.set(DtorState::RunningOrHasRun);
1033             drop(value);
1034         }
1035     }
1036 }
1037
1038 #[doc(hidden)]
1039 pub mod os {
1040     use super::lazy::LazyKeyInner;
1041     use crate::cell::Cell;
1042     use crate::fmt;
1043     use crate::marker;
1044     use crate::ptr;
1045     use crate::sys_common::thread_local_key::StaticKey as OsStaticKey;
1046
1047     pub struct Key<T> {
1048         // OS-TLS key that we'll use to key off.
1049         os: OsStaticKey,
1050         marker: marker::PhantomData<Cell<T>>,
1051     }
1052
1053     impl<T> fmt::Debug for Key<T> {
1054         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1055             f.debug_struct("Key").finish_non_exhaustive()
1056         }
1057     }
1058
1059     unsafe impl<T> Sync for Key<T> {}
1060
1061     struct Value<T: 'static> {
1062         inner: LazyKeyInner<T>,
1063         key: &'static Key<T>,
1064     }
1065
1066     impl<T: 'static> Key<T> {
1067         #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
1068         pub const fn new() -> Key<T> {
1069             Key { os: OsStaticKey::new(Some(destroy_value::<T>)), marker: marker::PhantomData }
1070         }
1071
1072         /// It is a requirement for the caller to ensure that no mutable
1073         /// reference is active when this method is called.
1074         pub unsafe fn get(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> {
1075             // SAFETY: See the documentation for this method.
1076             let ptr = unsafe { self.os.get() as *mut Value<T> };
1077             if ptr.addr() > 1 {
1078                 // SAFETY: the check ensured the pointer is safe (its destructor
1079                 // is not running) + it is coming from a trusted source (self).
1080                 if let Some(ref value) = unsafe { (*ptr).inner.get() } {
1081                     return Some(value);
1082                 }
1083             }
1084             // SAFETY: At this point we are sure we have no value and so
1085             // initializing (or trying to) is safe.
1086             unsafe { self.try_initialize(init) }
1087         }
1088
1089         // `try_initialize` is only called once per os thread local variable,
1090         // except in corner cases where thread_local dtors reference other
1091         // thread_local's, or it is being recursively initialized.
1092         unsafe fn try_initialize(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> {
1093             // SAFETY: No mutable references are ever handed out meaning getting
1094             // the value is ok.
1095             let ptr = unsafe { self.os.get() as *mut Value<T> };
1096             if ptr.addr() == 1 {
1097                 // destructor is running
1098                 return None;
1099             }
1100
1101             let ptr = if ptr.is_null() {
1102                 // If the lookup returned null, we haven't initialized our own
1103                 // local copy, so do that now.
1104                 let ptr: Box<Value<T>> = box Value { inner: LazyKeyInner::new(), key: self };
1105                 let ptr = Box::into_raw(ptr);
1106                 // SAFETY: At this point we are sure there is no value inside
1107                 // ptr so setting it will not affect anyone else.
1108                 unsafe {
1109                     self.os.set(ptr as *mut u8);
1110                 }
1111                 ptr
1112             } else {
1113                 // recursive initialization
1114                 ptr
1115             };
1116
1117             // SAFETY: ptr has been ensured as non-NUL just above an so can be
1118             // dereferenced safely.
1119             unsafe { Some((*ptr).inner.initialize(init)) }
1120         }
1121     }
1122
1123     unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) {
1124         // SAFETY:
1125         //
1126         // The OS TLS ensures that this key contains a null value when this
1127         // destructor starts to run. We set it back to a sentinel value of 1 to
1128         // ensure that any future calls to `get` for this thread will return
1129         // `None`.
1130         //
1131         // Note that to prevent an infinite loop we reset it back to null right
1132         // before we return from the destructor ourselves.
1133         unsafe {
1134             let ptr = Box::from_raw(ptr as *mut Value<T>);
1135             let key = ptr.key;
1136             key.os.set(ptr::invalid_mut(1));
1137             drop(ptr);
1138             key.os.set(ptr::null_mut());
1139         }
1140     }
1141 }