]> git.lizzy.rs Git - rust.git/blob - library/std/src/thread/local.rs
Rollup merge of #86673 - m-ou-se:disjoint-capture-edition-lint, r=nikomatsakis
[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::error::Error;
12 use crate::fmt;
13
14 /// A thread local storage key which owns its contents.
15 ///
16 /// This key uses the fastest possible implementation available to it for the
17 /// target platform. It is instantiated with the [`thread_local!`] macro and the
18 /// primary method is the [`with`] method.
19 ///
20 /// The [`with`] method yields a reference to the contained value which cannot be
21 /// sent across threads or escape the given closure.
22 ///
23 /// # Initialization and Destruction
24 ///
25 /// Initialization is dynamically performed on the first call to [`with`]
26 /// within a thread, and values that implement [`Drop`] get destructed when a
27 /// thread exits. Some caveats apply, which are explained below.
28 ///
29 /// A `LocalKey`'s initializer cannot recursively depend on itself, and using
30 /// a `LocalKey` in this way will cause the initializer to infinitely recurse
31 /// on the first call to `with`.
32 ///
33 /// # Examples
34 ///
35 /// ```
36 /// use std::cell::RefCell;
37 /// use std::thread;
38 ///
39 /// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
40 ///
41 /// FOO.with(|f| {
42 ///     assert_eq!(*f.borrow(), 1);
43 ///     *f.borrow_mut() = 2;
44 /// });
45 ///
46 /// // each thread starts out with the initial value of 1
47 /// let t = thread::spawn(move|| {
48 ///     FOO.with(|f| {
49 ///         assert_eq!(*f.borrow(), 1);
50 ///         *f.borrow_mut() = 3;
51 ///     });
52 /// });
53 ///
54 /// // wait for the thread to complete and bail out on panic
55 /// t.join().unwrap();
56 ///
57 /// // we retain our original value of 2 despite the child thread
58 /// FOO.with(|f| {
59 ///     assert_eq!(*f.borrow(), 2);
60 /// });
61 /// ```
62 ///
63 /// # Platform-specific behavior
64 ///
65 /// Note that a "best effort" is made to ensure that destructors for types
66 /// stored in thread local storage are run, but not all platforms can guarantee
67 /// that destructors will be run for all types in thread local storage. For
68 /// example, there are a number of known caveats where destructors are not run:
69 ///
70 /// 1. On Unix systems when pthread-based TLS is being used, destructors will
71 ///    not be run for TLS values on the main thread when it exits. Note that the
72 ///    application will exit immediately after the main thread exits as well.
73 /// 2. On all platforms it's possible for TLS to re-initialize other TLS slots
74 ///    during destruction. Some platforms ensure that this cannot happen
75 ///    infinitely by preventing re-initialization of any slot that has been
76 ///    destroyed, but not all platforms have this guard. Those platforms that do
77 ///    not guard typically have a synthetic limit after which point no more
78 ///    destructors are run.
79 ///
80 /// [`with`]: LocalKey::with
81 #[stable(feature = "rust1", since = "1.0.0")]
82 pub struct LocalKey<T: 'static> {
83     // This outer `LocalKey<T>` type is what's going to be stored in statics,
84     // but actual data inside will sometimes be tagged with #[thread_local].
85     // It's not valid for a true static to reference a #[thread_local] static,
86     // so we get around that by exposing an accessor through a layer of function
87     // indirection (this thunk).
88     //
89     // Note that the thunk is itself unsafe because the returned lifetime of the
90     // slot where data lives, `'static`, is not actually valid. The lifetime
91     // here is actually slightly shorter than the currently running thread!
92     //
93     // Although this is an extra layer of indirection, it should in theory be
94     // trivially devirtualizable by LLVM because the value of `inner` never
95     // changes and the constant should be readonly within a crate. This mainly
96     // only runs into problems when TLS statics are exported across crates.
97     inner: unsafe fn() -> Option<&'static T>,
98 }
99
100 #[stable(feature = "std_debug", since = "1.16.0")]
101 impl<T: 'static> fmt::Debug for LocalKey<T> {
102     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103         f.debug_struct("LocalKey").finish_non_exhaustive()
104     }
105 }
106
107 /// Declare a new thread local storage key of type [`std::thread::LocalKey`].
108 ///
109 /// # Syntax
110 ///
111 /// The macro wraps any number of static declarations and makes them thread local.
112 /// Publicity and attributes for each static are allowed. Example:
113 ///
114 /// ```
115 /// use std::cell::RefCell;
116 /// thread_local! {
117 ///     pub static FOO: RefCell<u32> = RefCell::new(1);
118 ///
119 ///     #[allow(unused)]
120 ///     static BAR: RefCell<f32> = RefCell::new(1.0);
121 /// }
122 /// # fn main() {}
123 /// ```
124 ///
125 /// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
126 /// information.
127 ///
128 /// [`std::thread::LocalKey`]: crate::thread::LocalKey
129 #[macro_export]
130 #[stable(feature = "rust1", since = "1.0.0")]
131 #[allow_internal_unstable(thread_local_internals)]
132 macro_rules! thread_local {
133     // empty (base case for the recursion)
134     () => {};
135
136     ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => (
137         $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
138         $crate::thread_local!($($rest)*);
139     );
140
141     ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => (
142         $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
143     );
144
145     // process multiple declarations
146     ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
147         $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
148         $crate::thread_local!($($rest)*);
149     );
150
151     // handle a single declaration
152     ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
153         $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
154     );
155 }
156
157 #[doc(hidden)]
158 #[unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")]
159 #[macro_export]
160 #[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
161 #[allow_internal_unsafe]
162 macro_rules! __thread_local_inner {
163     // used to generate the `LocalKey` value for const-initialized thread locals
164     (@key $t:ty, const $init:expr) => {{
165         #[cfg_attr(not(windows), inline)] // see comments below
166         unsafe fn __getit() -> $crate::option::Option<&'static $t> {
167             const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local();
168
169             // wasm without atomics maps directly to `static mut`, and dtors
170             // aren't implemented because thread dtors aren't really a thing
171             // on wasm right now
172             //
173             // FIXME(#84224) this should come after the `target_thread_local`
174             // block.
175             #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
176             {
177                 static mut VAL: $t = $init;
178                 Some(&VAL)
179             }
180
181             // If the platform has support for `#[thread_local]`, use it.
182             #[cfg(all(
183                 target_thread_local,
184                 not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
185             ))]
186             {
187                 // If a dtor isn't needed we can do something "very raw" and
188                 // just get going.
189                 if !$crate::mem::needs_drop::<$t>() {
190                     #[thread_local]
191                     static mut VAL: $t = $init;
192                     unsafe {
193                         return Some(&VAL)
194                     }
195                 }
196
197                 #[thread_local]
198                 static mut VAL: $t = $init;
199                 // 0 == dtor not registered
200                 // 1 == dtor registered, dtor not run
201                 // 2 == dtor registered and is running or has run
202                 #[thread_local]
203                 static mut STATE: u8 = 0;
204
205                 unsafe extern "C" fn destroy(ptr: *mut u8) {
206                     let ptr = ptr as *mut $t;
207
208                     unsafe {
209                         debug_assert_eq!(STATE, 1);
210                         STATE = 2;
211                         $crate::ptr::drop_in_place(ptr);
212                     }
213                 }
214
215                 unsafe {
216                     match STATE {
217                         // 0 == we haven't registered a destructor, so do
218                         //   so now.
219                         0 => {
220                             $crate::thread::__FastLocalKeyInner::<$t>::register_dtor(
221                                 $crate::ptr::addr_of_mut!(VAL) as *mut u8,
222                                 destroy,
223                             );
224                             STATE = 1;
225                             Some(&VAL)
226                         }
227                         // 1 == the destructor is registered and the value
228                         //   is valid, so return the pointer.
229                         1 => Some(&VAL),
230                         // otherwise the destructor has already run, so we
231                         // can't give access.
232                         _ => None,
233                     }
234                 }
235             }
236
237             // On platforms without `#[thread_local]` we fall back to the
238             // same implementation as below for os thread locals.
239             #[cfg(all(
240                 not(target_thread_local),
241                 not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
242             ))]
243             {
244                 #[inline]
245                 const fn __init() -> $t { $init }
246                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
247                     $crate::thread::__OsLocalKeyInner::new();
248                 #[allow(unused_unsafe)]
249                 unsafe { __KEY.get(__init) }
250             }
251         }
252
253         unsafe {
254             $crate::thread::LocalKey::new(__getit)
255         }
256     }};
257
258     // used to generate the `LocalKey` value for `thread_local!`
259     (@key $t:ty, $init:expr) => {
260         {
261             #[inline]
262             fn __init() -> $t { $init }
263
264             // When reading this function you might ask "why is this inlined
265             // everywhere other than Windows?", and that's a very reasonable
266             // question to ask. The short story is that it segfaults rustc if
267             // this function is inlined. The longer story is that Windows looks
268             // to not support `extern` references to thread locals across DLL
269             // boundaries. This appears to at least not be supported in the ABI
270             // that LLVM implements.
271             //
272             // Because of this we never inline on Windows, but we do inline on
273             // other platforms (where external references to thread locals
274             // across DLLs are supported). A better fix for this would be to
275             // inline this function on Windows, but only for "statically linked"
276             // components. For example if two separately compiled rlibs end up
277             // getting linked into a DLL then it's fine to inline this function
278             // across that boundary. It's only not fine to inline this function
279             // across a DLL boundary. Unfortunately rustc doesn't currently
280             // have this sort of logic available in an attribute, and it's not
281             // clear that rustc is even equipped to answer this (it's more of a
282             // Cargo question kinda). This means that, unfortunately, Windows
283             // gets the pessimistic path for now where it's never inlined.
284             //
285             // The issue of "should enable on Windows sometimes" is #84933
286             #[cfg_attr(not(windows), inline)]
287             unsafe fn __getit() -> $crate::option::Option<&'static $t> {
288                 #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
289                 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
290                     $crate::thread::__StaticLocalKeyInner::new();
291
292                 #[thread_local]
293                 #[cfg(all(
294                     target_thread_local,
295                     not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
296                 ))]
297                 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
298                     $crate::thread::__FastLocalKeyInner::new();
299
300                 #[cfg(all(
301                     not(target_thread_local),
302                     not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
303                 ))]
304                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
305                     $crate::thread::__OsLocalKeyInner::new();
306
307                 // FIXME: remove the #[allow(...)] marker when macros don't
308                 // raise warning for missing/extraneous unsafe blocks anymore.
309                 // See https://github.com/rust-lang/rust/issues/74838.
310                 #[allow(unused_unsafe)]
311                 unsafe { __KEY.get(__init) }
312             }
313
314             unsafe {
315                 $crate::thread::LocalKey::new(__getit)
316             }
317         }
318     };
319     ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
320         $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
321             $crate::__thread_local_inner!(@key $t, $($init)*);
322     }
323 }
324
325 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
326 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
327 #[non_exhaustive]
328 #[derive(Clone, Copy, Eq, PartialEq)]
329 pub struct AccessError;
330
331 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
332 impl fmt::Debug for AccessError {
333     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334         f.debug_struct("AccessError").finish()
335     }
336 }
337
338 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
339 impl fmt::Display for AccessError {
340     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341         fmt::Display::fmt("already destroyed", f)
342     }
343 }
344
345 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
346 impl Error for AccessError {}
347
348 impl<T: 'static> LocalKey<T> {
349     #[doc(hidden)]
350     #[unstable(
351         feature = "thread_local_internals",
352         reason = "recently added to create a key",
353         issue = "none"
354     )]
355     #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
356     pub const unsafe fn new(inner: unsafe fn() -> Option<&'static T>) -> LocalKey<T> {
357         LocalKey { inner }
358     }
359
360     /// Acquires a reference to the value in this TLS key.
361     ///
362     /// This will lazily initialize the value if this thread has not referenced
363     /// this key yet.
364     ///
365     /// # Panics
366     ///
367     /// This function will `panic!()` if the key currently has its
368     /// destructor running, and it **may** panic if the destructor has
369     /// previously been run for this thread.
370     #[stable(feature = "rust1", since = "1.0.0")]
371     pub fn with<F, R>(&'static self, f: F) -> R
372     where
373         F: FnOnce(&T) -> R,
374     {
375         self.try_with(f).expect(
376             "cannot access a Thread Local Storage value \
377              during or after destruction",
378         )
379     }
380
381     /// Acquires a reference to the value in this TLS key.
382     ///
383     /// This will lazily initialize the value if this thread has not referenced
384     /// this key yet. If the key has been destroyed (which may happen if this is called
385     /// in a destructor), this function will return an [`AccessError`].
386     ///
387     /// # Panics
388     ///
389     /// This function will still `panic!()` if the key is uninitialized and the
390     /// key's initializer panics.
391     #[stable(feature = "thread_local_try_with", since = "1.26.0")]
392     #[inline]
393     pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
394     where
395         F: FnOnce(&T) -> R,
396     {
397         unsafe {
398             let thread_local = (self.inner)().ok_or(AccessError)?;
399             Ok(f(thread_local))
400         }
401     }
402 }
403
404 mod lazy {
405     use crate::cell::UnsafeCell;
406     use crate::hint;
407     use crate::mem;
408
409     pub struct LazyKeyInner<T> {
410         inner: UnsafeCell<Option<T>>,
411     }
412
413     impl<T> LazyKeyInner<T> {
414         pub const fn new() -> LazyKeyInner<T> {
415             LazyKeyInner { inner: UnsafeCell::new(None) }
416         }
417
418         pub unsafe fn get(&self) -> Option<&'static T> {
419             // SAFETY: The caller must ensure no reference is ever handed out to
420             // the inner cell nor mutable reference to the Option<T> inside said
421             // cell. This make it safe to hand a reference, though the lifetime
422             // of 'static is itself unsafe, making the get method unsafe.
423             unsafe { (*self.inner.get()).as_ref() }
424         }
425
426         /// The caller must ensure that no reference is active: this method
427         /// needs unique access.
428         pub unsafe fn initialize<F: FnOnce() -> T>(&self, init: F) -> &'static T {
429             // Execute the initialization up front, *then* move it into our slot,
430             // just in case initialization fails.
431             let value = init();
432             let ptr = self.inner.get();
433
434             // SAFETY:
435             //
436             // note that this can in theory just be `*ptr = Some(value)`, but due to
437             // the compiler will currently codegen that pattern with something like:
438             //
439             //      ptr::drop_in_place(ptr)
440             //      ptr::write(ptr, Some(value))
441             //
442             // Due to this pattern it's possible for the destructor of the value in
443             // `ptr` (e.g., if this is being recursively initialized) to re-access
444             // TLS, in which case there will be a `&` and `&mut` pointer to the same
445             // value (an aliasing violation). To avoid setting the "I'm running a
446             // destructor" flag we just use `mem::replace` which should sequence the
447             // operations a little differently and make this safe to call.
448             //
449             // The precondition also ensures that we are the only one accessing
450             // `self` at the moment so replacing is fine.
451             unsafe {
452                 let _ = mem::replace(&mut *ptr, Some(value));
453             }
454
455             // SAFETY: With the call to `mem::replace` it is guaranteed there is
456             // a `Some` behind `ptr`, not a `None` so `unreachable_unchecked`
457             // will never be reached.
458             unsafe {
459                 // After storing `Some` we want to get a reference to the contents of
460                 // what we just stored. While we could use `unwrap` here and it should
461                 // always work it empirically doesn't seem to always get optimized away,
462                 // which means that using something like `try_with` can pull in
463                 // panicking code and cause a large size bloat.
464                 match *ptr {
465                     Some(ref x) => x,
466                     None => hint::unreachable_unchecked(),
467                 }
468             }
469         }
470
471         /// The other methods hand out references while taking &self.
472         /// As such, callers of this method must ensure no `&` and `&mut` are
473         /// available and used at the same time.
474         #[allow(unused)]
475         pub unsafe fn take(&mut self) -> Option<T> {
476             // SAFETY: See doc comment for this method.
477             unsafe { (*self.inner.get()).take() }
478         }
479     }
480 }
481
482 /// On some platforms like wasm32 there's no threads, so no need to generate
483 /// thread locals and we can instead just use plain statics!
484 #[doc(hidden)]
485 #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
486 pub mod statik {
487     use super::lazy::LazyKeyInner;
488     use crate::fmt;
489
490     pub struct Key<T> {
491         inner: LazyKeyInner<T>,
492     }
493
494     unsafe impl<T> Sync for Key<T> {}
495
496     impl<T> fmt::Debug for Key<T> {
497         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
498             f.debug_struct("Key").finish_non_exhaustive()
499         }
500     }
501
502     impl<T> Key<T> {
503         pub const fn new() -> Key<T> {
504             Key { inner: LazyKeyInner::new() }
505         }
506
507         pub unsafe fn get(&self, init: fn() -> T) -> Option<&'static T> {
508             // SAFETY: The caller must ensure no reference is ever handed out to
509             // the inner cell nor mutable reference to the Option<T> inside said
510             // cell. This make it safe to hand a reference, though the lifetime
511             // of 'static is itself unsafe, making the get method unsafe.
512             let value = unsafe {
513                 match self.inner.get() {
514                     Some(ref value) => value,
515                     None => self.inner.initialize(init),
516                 }
517             };
518
519             Some(value)
520         }
521     }
522 }
523
524 #[doc(hidden)]
525 #[cfg(target_thread_local)]
526 pub mod fast {
527     use super::lazy::LazyKeyInner;
528     use crate::cell::Cell;
529     use crate::fmt;
530     use crate::mem;
531     use crate::sys::thread_local_dtor::register_dtor;
532
533     #[derive(Copy, Clone)]
534     enum DtorState {
535         Unregistered,
536         Registered,
537         RunningOrHasRun,
538     }
539
540     // This data structure has been carefully constructed so that the fast path
541     // only contains one branch on x86. That optimization is necessary to avoid
542     // duplicated tls lookups on OSX.
543     //
544     // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
545     pub struct Key<T> {
546         // If `LazyKeyInner::get` returns `None`, that indicates either:
547         //   * The value has never been initialized
548         //   * The value is being recursively initialized
549         //   * The value has already been destroyed or is being destroyed
550         // To determine which kind of `None`, check `dtor_state`.
551         //
552         // This is very optimizer friendly for the fast path - initialized but
553         // not yet dropped.
554         inner: LazyKeyInner<T>,
555
556         // Metadata to keep track of the state of the destructor. Remember that
557         // this variable is thread-local, not global.
558         dtor_state: Cell<DtorState>,
559     }
560
561     impl<T> fmt::Debug for Key<T> {
562         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563             f.debug_struct("Key").finish_non_exhaustive()
564         }
565     }
566
567     impl<T> Key<T> {
568         pub const fn new() -> Key<T> {
569             Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }
570         }
571
572         // note that this is just a publically-callable function only for the
573         // const-initialized form of thread locals, basically a way to call the
574         // free `register_dtor` function defined elsewhere in libstd.
575         pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
576             unsafe {
577                 register_dtor(a, dtor);
578             }
579         }
580
581         pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
582             // SAFETY: See the definitions of `LazyKeyInner::get` and
583             // `try_initialize` for more informations.
584             //
585             // The caller must ensure no mutable references are ever active to
586             // the inner cell or the inner T when this is called.
587             // The `try_initialize` is dependant on the passed `init` function
588             // for this.
589             unsafe {
590                 match self.inner.get() {
591                     Some(val) => Some(val),
592                     None => self.try_initialize(init),
593                 }
594             }
595         }
596
597         // `try_initialize` is only called once per fast thread local variable,
598         // except in corner cases where thread_local dtors reference other
599         // thread_local's, or it is being recursively initialized.
600         //
601         // Macos: Inlining this function can cause two `tlv_get_addr` calls to
602         // be performed for every call to `Key::get`.
603         // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
604         #[inline(never)]
605         unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
606             // SAFETY: See comment above (this function doc).
607             if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } {
608                 // SAFETY: See comment above (his function doc).
609                 Some(unsafe { self.inner.initialize(init) })
610             } else {
611                 None
612             }
613         }
614
615         // `try_register_dtor` is only called once per fast thread local
616         // variable, except in corner cases where thread_local dtors reference
617         // other thread_local's, or it is being recursively initialized.
618         unsafe fn try_register_dtor(&self) -> bool {
619             match self.dtor_state.get() {
620                 DtorState::Unregistered => {
621                     // SAFETY: dtor registration happens before initialization.
622                     // Passing `self` as a pointer while using `destroy_value<T>`
623                     // is safe because the function will build a pointer to a
624                     // Key<T>, which is the type of self and so find the correct
625                     // size.
626                     unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::<T>) };
627                     self.dtor_state.set(DtorState::Registered);
628                     true
629                 }
630                 DtorState::Registered => {
631                     // recursively initialized
632                     true
633                 }
634                 DtorState::RunningOrHasRun => false,
635             }
636         }
637     }
638
639     unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) {
640         let ptr = ptr as *mut Key<T>;
641
642         // SAFETY:
643         //
644         // The pointer `ptr` has been built just above and comes from
645         // `try_register_dtor` where it is originally a Key<T> coming from `self`,
646         // making it non-NUL and of the correct type.
647         //
648         // Right before we run the user destructor be sure to set the
649         // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
650         // causes future calls to `get` to run `try_initialize_drop` again,
651         // which will now fail, and return `None`.
652         unsafe {
653             let value = (*ptr).inner.take();
654             (*ptr).dtor_state.set(DtorState::RunningOrHasRun);
655             drop(value);
656         }
657     }
658 }
659
660 #[doc(hidden)]
661 pub mod os {
662     use super::lazy::LazyKeyInner;
663     use crate::cell::Cell;
664     use crate::fmt;
665     use crate::marker;
666     use crate::ptr;
667     use crate::sys_common::thread_local_key::StaticKey as OsStaticKey;
668
669     pub struct Key<T> {
670         // OS-TLS key that we'll use to key off.
671         os: OsStaticKey,
672         marker: marker::PhantomData<Cell<T>>,
673     }
674
675     impl<T> fmt::Debug for Key<T> {
676         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
677             f.debug_struct("Key").finish_non_exhaustive()
678         }
679     }
680
681     unsafe impl<T> Sync for Key<T> {}
682
683     struct Value<T: 'static> {
684         inner: LazyKeyInner<T>,
685         key: &'static Key<T>,
686     }
687
688     impl<T: 'static> Key<T> {
689         #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
690         pub const fn new() -> Key<T> {
691             Key { os: OsStaticKey::new(Some(destroy_value::<T>)), marker: marker::PhantomData }
692         }
693
694         /// It is a requirement for the caller to ensure that no mutable
695         /// reference is active when this method is called.
696         pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> {
697             // SAFETY: See the documentation for this method.
698             let ptr = unsafe { self.os.get() as *mut Value<T> };
699             if ptr as usize > 1 {
700                 // SAFETY: the check ensured the pointer is safe (its destructor
701                 // is not running) + it is coming from a trusted source (self).
702                 if let Some(ref value) = unsafe { (*ptr).inner.get() } {
703                     return Some(value);
704                 }
705             }
706             // SAFETY: At this point we are sure we have no value and so
707             // initializing (or trying to) is safe.
708             unsafe { self.try_initialize(init) }
709         }
710
711         // `try_initialize` is only called once per os thread local variable,
712         // except in corner cases where thread_local dtors reference other
713         // thread_local's, or it is being recursively initialized.
714         unsafe fn try_initialize(&'static self, init: fn() -> T) -> Option<&'static T> {
715             // SAFETY: No mutable references are ever handed out meaning getting
716             // the value is ok.
717             let ptr = unsafe { self.os.get() as *mut Value<T> };
718             if ptr as usize == 1 {
719                 // destructor is running
720                 return None;
721             }
722
723             let ptr = if ptr.is_null() {
724                 // If the lookup returned null, we haven't initialized our own
725                 // local copy, so do that now.
726                 let ptr: Box<Value<T>> = box Value { inner: LazyKeyInner::new(), key: self };
727                 let ptr = Box::into_raw(ptr);
728                 // SAFETY: At this point we are sure there is no value inside
729                 // ptr so setting it will not affect anyone else.
730                 unsafe {
731                     self.os.set(ptr as *mut u8);
732                 }
733                 ptr
734             } else {
735                 // recursive initialization
736                 ptr
737             };
738
739             // SAFETY: ptr has been ensured as non-NUL just above an so can be
740             // dereferenced safely.
741             unsafe { Some((*ptr).inner.initialize(init)) }
742         }
743     }
744
745     unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) {
746         // SAFETY:
747         //
748         // The OS TLS ensures that this key contains a null value when this
749         // destructor starts to run. We set it back to a sentinel value of 1 to
750         // ensure that any future calls to `get` for this thread will return
751         // `None`.
752         //
753         // Note that to prevent an infinite loop we reset it back to null right
754         // before we return from the destructor ourselves.
755         unsafe {
756             let ptr = Box::from_raw(ptr as *mut Value<T>);
757             let key = ptr.key;
758             key.os.set(1 as *mut u8);
759             drop(ptr);
760             key.os.set(ptr::null_mut());
761         }
762     }
763 }