std/sys/thread_local/
no_threads.rs1use crate::cell::{Cell, UnsafeCell};
5use crate::mem::MaybeUninit;
6use crate::ptr;
7
8#[doc(hidden)]
9#[allow_internal_unstable(thread_local_internals)]
10#[allow_internal_unsafe]
11#[unstable(feature = "thread_local_internals", issue = "none")]
12#[rustc_macro_transparency = "semitransparent"]
13pub macro thread_local_inner {
14 (@key $t:ty, $(#[$align_attr:meta])*, const $init:expr) => {{
16 const __RUST_STD_INTERNAL_INIT: $t = $init;
17
18 unsafe {
20 $crate::thread::LocalKey::new(|_| {
21 $(#[$align_attr])*
22 static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::EagerStorage<$t> =
23 $crate::thread::local_impl::EagerStorage { value: __RUST_STD_INTERNAL_INIT };
24 &__RUST_STD_INTERNAL_VAL.value
25 })
26 }
27 }},
28
29 (@key $t:ty, $(#[$align_attr:meta])*, $init:expr) => {{
31 #[inline]
32 fn __rust_std_internal_init_fn() -> $t { $init }
33
34 unsafe {
35 $crate::thread::LocalKey::new(|__rust_std_internal_init| {
36 $(#[$align_attr])*
37 static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::LazyStorage<$t> = $crate::thread::local_impl::LazyStorage::new();
38 __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, __rust_std_internal_init_fn)
39 })
40 }
41 }},
42}
43
44#[allow(missing_debug_implementations)]
45#[repr(transparent)] pub struct EagerStorage<T> {
47 pub value: T,
48}
49
50unsafe impl<T> Sync for EagerStorage<T> {}
52
53#[derive(Clone, Copy, PartialEq, Eq)]
54enum State {
55 Initial,
56 Alive,
57 Destroying,
58}
59
60#[allow(missing_debug_implementations)]
61#[repr(C)]
62pub struct LazyStorage<T> {
63 value: UnsafeCell<MaybeUninit<T>>,
65 state: Cell<State>,
66}
67
68impl<T> LazyStorage<T> {
69 pub const fn new() -> LazyStorage<T> {
70 LazyStorage {
71 value: UnsafeCell::new(MaybeUninit::uninit()),
72 state: Cell::new(State::Initial),
73 }
74 }
75
76 #[inline]
82 pub fn get(&'static self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
83 if self.state.get() == State::Alive {
84 self.value.get() as *const T
85 } else {
86 self.initialize(i, f)
87 }
88 }
89
90 #[cold]
91 fn initialize(&'static self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
92 let value = i.and_then(Option::take).unwrap_or_else(f);
93
94 if self.state.get() == State::Alive {
97 self.state.set(State::Destroying);
98 unsafe {
100 ptr::drop_in_place(self.value.get() as *mut T);
101 }
102 self.state.set(State::Initial);
103 }
104
105 if self.state.get() == State::Destroying {
107 panic!("Attempted to initialize thread-local while it is being dropped");
108 }
109
110 unsafe {
111 self.value.get().write(MaybeUninit::new(value));
112 }
113 self.state.set(State::Alive);
114
115 self.value.get() as *const T
116 }
117}
118
119unsafe impl<T> Sync for LazyStorage<T> {}
121
122#[rustc_macro_transparency = "semitransparent"]
123pub(crate) macro local_pointer {
124 () => {},
125 ($vis:vis static $name:ident; $($rest:tt)*) => {
126 $vis static $name: $crate::sys::thread_local::LocalPointer = $crate::sys::thread_local::LocalPointer::__new();
127 $crate::sys::thread_local::local_pointer! { $($rest)* }
128 },
129}
130
131pub(crate) struct LocalPointer {
132 p: Cell<*mut ()>,
133}
134
135impl LocalPointer {
136 pub const fn __new() -> LocalPointer {
137 LocalPointer { p: Cell::new(ptr::null_mut()) }
138 }
139
140 pub fn get(&self) -> *mut () {
141 self.p.get()
142 }
143
144 pub fn set(&self, p: *mut ()) {
145 self.p.set(p)
146 }
147}
148
149unsafe impl Sync for LocalPointer {}