std/sys/thread_local/
no_threads.rs1use crate::cell::{Cell, UnsafeCell};
5use crate::ptr;
6
7#[doc(hidden)]
8#[allow_internal_unstable(thread_local_internals)]
9#[allow_internal_unsafe]
10#[unstable(feature = "thread_local_internals", issue = "none")]
11#[rustc_macro_transparency = "semitransparent"]
12pub macro thread_local_inner {
13 (@key $t:ty, const $init:expr) => {{
15 const __INIT: $t = $init;
16
17 unsafe {
19 $crate::thread::LocalKey::new(|_| {
20 static VAL: $crate::thread::local_impl::EagerStorage<$t> =
21 $crate::thread::local_impl::EagerStorage { value: __INIT };
22 &VAL.value
23 })
24 }
25 }},
26
27 (@key $t:ty, $init:expr) => {{
29 #[inline]
30 fn __init() -> $t { $init }
31
32 unsafe {
33 use $crate::thread::LocalKey;
34 use $crate::thread::local_impl::LazyStorage;
35
36 LocalKey::new(|init| {
37 static VAL: LazyStorage<$t> = LazyStorage::new();
38 VAL.get(init, __init)
39 })
40 }
41 }},
42 ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
43 $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
44 $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
45 },
46}
47
48#[allow(missing_debug_implementations)]
49pub struct EagerStorage<T> {
50 pub value: T,
51}
52
53unsafe impl<T> Sync for EagerStorage<T> {}
55
56#[allow(missing_debug_implementations)]
57pub struct LazyStorage<T> {
58 value: UnsafeCell<Option<T>>,
59}
60
61impl<T> LazyStorage<T> {
62 pub const fn new() -> LazyStorage<T> {
63 LazyStorage { value: UnsafeCell::new(None) }
64 }
65
66 #[inline]
72 pub fn get(&'static self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
73 let value = unsafe { &*self.value.get() };
74 match value {
75 Some(v) => v,
76 None => self.initialize(i, f),
77 }
78 }
79
80 #[cold]
81 fn initialize(&'static self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
82 let value = i.and_then(Option::take).unwrap_or_else(f);
83 unsafe {
87 self.value.get().replace(Some(value));
88 }
89 unsafe { (*self.value.get()).as_ref().unwrap_unchecked() }
91 }
92}
93
94unsafe impl<T> Sync for LazyStorage<T> {}
96
97#[rustc_macro_transparency = "semitransparent"]
98pub(crate) macro local_pointer {
99 () => {},
100 ($vis:vis static $name:ident; $($rest:tt)*) => {
101 $vis static $name: $crate::sys::thread_local::LocalPointer = $crate::sys::thread_local::LocalPointer::__new();
102 $crate::sys::thread_local::local_pointer! { $($rest)* }
103 },
104}
105
106pub(crate) struct LocalPointer {
107 p: Cell<*mut ()>,
108}
109
110impl LocalPointer {
111 pub const fn __new() -> LocalPointer {
112 LocalPointer { p: Cell::new(ptr::null_mut()) }
113 }
114
115 pub fn get(&self) -> *mut () {
116 self.p.get()
117 }
118
119 pub fn set(&self, p: *mut ()) {
120 self.p.set(p)
121 }
122}
123
124unsafe impl Sync for LocalPointer {}