1use crate::cell::UnsafeCell;
2use crate::mem::ManuallyDrop;
3use crate::ops::Deref;
4use crate::panic::{RefUnwindSafe, UnwindSafe};
5use crate::sync::Once;
6use crate::{fmt, ptr};
7
8use super::once::ExclusiveState;
9
10// We use the state of a Once as discriminant value. Upon creation, the state is
11// "incomplete" and `f` contains the initialization closure. In the first call to
12// `call_once`, `f` is taken and run. If it succeeds, `value` is set and the state
13// is changed to "complete". If it panics, the Once is poisoned, so none of the
14// two fields is initialized.
15union Data<T, F> {
16 value: ManuallyDrop<T>,
17 f: ManuallyDrop<F>,
18}
19
20/// A value which is initialized on the first access.
21///
22/// This type is a thread-safe [`LazyCell`], and can be used in statics.
23/// Since initialization may be called from multiple threads, any
24/// dereferencing call will block the calling thread if another
25/// initialization routine is currently running.
26///
27/// [`LazyCell`]: crate::cell::LazyCell
28///
29/// # Examples
30///
31/// Initialize static variables with `LazyLock`.
32///
33/// ```
34/// #![feature(lazy_cell)]
35///
36/// use std::collections::HashMap;
37///
38/// use std::sync::LazyLock;
39///
40/// static HASHMAP: LazyLock<HashMap<i32, String>> = LazyLock::new(|| {
41/// println!("initializing");
42/// let mut m = HashMap::new();
43/// m.insert(13, "Spica".to_string());
44/// m.insert(74, "Hoyten".to_string());
45/// m
46/// });
47///
48/// fn main() {
49/// println!("ready");
50/// std::thread::spawn(|| {
51/// println!("{:?}", HASHMAP.get(&13));
52/// }).join().unwrap();
53/// println!("{:?}", HASHMAP.get(&74));
54///
55/// // Prints:
56/// // ready
57/// // initializing
58/// // Some("Spica")
59/// // Some("Hoyten")
60/// }
61/// ```
62/// Initialize fields with `LazyLock`.
63/// ```
64/// #![feature(lazy_cell)]
65///
66/// use std::sync::LazyLock;
67///
68/// #[derive(Debug)]
69/// struct UseCellLock {
70/// number: LazyLock<u32>,
71/// }
72/// fn main() {
73/// let lock: LazyLock<u32> = LazyLock::new(|| 0u32);
74///
75/// let data = UseCellLock { number: lock };
76/// println!("{}", *data.number);
77/// }
78/// ```
79
80#[unstable(feature = "lazy_cell", issue = "109736")]
81pub struct LazyLock<T, F = fn() -> T> {
82 once: Once,
83 data: UnsafeCell<Data<T, F>>,
84}
85
86impl<T, F: FnOnce() -> T> LazyLock<T, F> {
87 /// Creates a new lazy value with the given initializing function.
88 #[inline]
89 #[unstable(feature = "lazy_cell", issue = "109736")]
90 pub const fn new(f: F) -> LazyLock<T, F> {
91 LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
92 }
93
94 /// Creates a new lazy value that is already initialized.
95 #[inline]
96 #[cfg(test)]
97 pub(crate) fn preinit(value: T) -> LazyLock<T, F> {
98 let once = Once::new();
99 once.call_once(|| {});
100 LazyLock { once, data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }) }
101 }
102
103 /// Consumes this `LazyLock` returning the stored value.
104 ///
105 /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
106 ///
107 /// # Examples
108 ///
109 /// ```
110 /// #![feature(lazy_cell)]
111 /// #![feature(lazy_cell_consume)]
112 ///
113 /// use std::sync::LazyLock;
114 ///
115 /// let hello = "Hello, World!".to_string();
116 ///
117 /// let lazy = LazyLock::new(|| hello.to_uppercase());
118 ///
119 /// assert_eq!(&*lazy, "HELLO, WORLD!");
120 /// assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
121 /// ```
122 #[unstable(feature = "lazy_cell_consume", issue = "109736")]
123 pub fn into_inner(mut this: Self) -> Result<T, F> {
124 let state = this.once.state();
125 match state {
126 ExclusiveState::Poisoned => panic!("LazyLock instance has previously been poisoned"),
127 state => {
128 let this = ManuallyDrop::new(this);
129 let data = unsafe { ptr::read(&this.data) }.into_inner();
130 match state {
131 ExclusiveState::Incomplete => Err(ManuallyDrop::into_inner(unsafe { data.f })),
132 ExclusiveState::Complete => Ok(ManuallyDrop::into_inner(unsafe { data.value })),
133 ExclusiveState::Poisoned => unreachable!(),
134 }
135 }
136 }
137 }
138
139 /// Forces the evaluation of this lazy value and returns a reference to
140 /// result. This is equivalent to the `Deref` impl, but is explicit.
141 ///
142 /// This method will block the calling thread if another initialization
143 /// routine is currently running.
144 ///
145 /// # Examples
146 ///
147 /// ```
148 /// #![feature(lazy_cell)]
149 ///
150 /// use std::sync::LazyLock;
151 ///
152 /// let lazy = LazyLock::new(|| 92);
153 ///
154 /// assert_eq!(LazyLock::force(&lazy), &92);
155 /// assert_eq!(&*lazy, &92);
156 /// ```
157 #[inline]
158 #[unstable(feature = "lazy_cell", issue = "109736")]
159 pub fn force(this: &LazyLock<T, F>) -> &T {
160 this.once.call_once(|| {
161 // SAFETY: `call_once` only runs this closure once, ever.
162 let data = unsafe { &mut *this.data.get() };
163 let f = unsafe { ManuallyDrop::take(&mut data.f) };
164 let value = f();
165 data.value = ManuallyDrop::new(value);
166 });
167
168 // SAFETY:
169 // There are four possible scenarios:
170 // * the closure was called and initialized `value`.
171 // * the closure was called and panicked, so this point is never reached.
172 // * the closure was not called, but a previous call initialized `value`.
173 // * the closure was not called because the Once is poisoned, so this point
174 // is never reached.
175 // So `value` has definitely been initialized and will not be modified again.
176 unsafe { &*(*this.data.get()).value }
177 }
178}
179
180impl<T, F> LazyLock<T, F> {
181 /// Get the inner value if it has already been initialized.
182 fn get(&self) -> Option<&T> {
183 if self.once.is_completed() {
184 // SAFETY:
185 // The closure has been run successfully, so `value` has been initialized
186 // and will not be modified again.
187 Some(unsafe { &*(*self.data.get()).value })
188 } else {
189 None
190 }
191 }
192}
193
194#[unstable(feature = "lazy_cell", issue = "109736")]
195impl<T, F> Drop for LazyLock<T, F> {
196 fn drop(&mut self) {
197 match self.once.state() {
198 ExclusiveState::Incomplete => unsafe { ManuallyDrop::drop(&mut self.data.get_mut().f) },
199 ExclusiveState::Complete => unsafe {
200 ManuallyDrop::drop(&mut self.data.get_mut().value)
201 },
202 ExclusiveState::Poisoned => {}
203 }
204 }
205}
206
207#[unstable(feature = "lazy_cell", issue = "109736")]
208impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
209 type Target = T;
210
211 /// Dereferences the value.
212 ///
213 /// This method will block the calling thread if another initialization
214 /// routine is currently running.
215 ///
216 #[inline]
217 fn deref(&self) -> &T {
218 LazyLock::force(self)
219 }
220}
221
222#[unstable(feature = "lazy_cell", issue = "109736")]
223impl<T: Default> Default for LazyLock<T> {
224 /// Creates a new lazy value using `Default` as the initializing function.
225 #[inline]
226 fn default() -> LazyLock<T> {
227 LazyLock::new(T::default)
228 }
229}
230
231#[unstable(feature = "lazy_cell", issue = "109736")]
232impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234 let mut d: DebugTuple<'_, '_> = f.debug_tuple(name:"LazyLock");
235 match self.get() {
236 Some(v: &T) => d.field(v),
237 None => d.field(&format_args!("<uninit>")),
238 };
239 d.finish()
240 }
241}
242
243// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
244// to not impl `Sync` for `F`.
245#[unstable(feature = "lazy_cell", issue = "109736")]
246unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
247// auto-derived `Send` impl is OK.
248
249#[unstable(feature = "lazy_cell", issue = "109736")]
250impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
251#[unstable(feature = "lazy_cell", issue = "109736")]
252impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}
253
254#[cfg(test)]
255mod tests;
256