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