1use crate::cell::UnsafeCell;
2use crate::fmt;
3use crate::marker::PhantomData;
4use crate::mem::MaybeUninit;
5use crate::panic::{RefUnwindSafe, UnwindSafe};
6use crate::sync::Once;
7
8/// A synchronization primitive which can be written to only once.
9///
10/// This type is a thread-safe [`OnceCell`], and can be used in statics.
11///
12/// [`OnceCell`]: crate::cell::OnceCell
13///
14/// # Examples
15///
16/// Using `OnceCell` to store a function’s previously computed value (a.k.a.
17/// ‘lazy static’ or ‘memoizing’):
18///
19/// ```
20/// use std::sync::OnceLock;
21///
22/// struct DeepThought {
23/// answer: String,
24/// }
25///
26/// impl DeepThought {
27/// # fn great_question() -> String {
28/// # "42".to_string()
29/// # }
30/// #
31/// fn new() -> Self {
32/// Self {
33/// // M3 Ultra takes about 16 million years in --release config
34/// answer: Self::great_question(),
35/// }
36/// }
37/// }
38///
39/// fn computation() -> &'static DeepThought {
40/// // n.b. static items do not call [`Drop`] on program termination, so if
41/// // [`DeepThought`] impls Drop, that will not be used for this instance.
42/// static COMPUTATION: OnceLock<DeepThought> = OnceLock::new();
43/// COMPUTATION.get_or_init(|| DeepThought::new())
44/// }
45///
46/// // The `DeepThought` is built, stored in the `OnceLock`, and returned.
47/// let _ = computation().answer;
48/// // The `DeepThought` is retrieved from the `OnceLock` and returned.
49/// let _ = computation().answer;
50/// ```
51///
52/// Writing to a `OnceLock` from a separate thread:
53///
54/// ```
55/// use std::sync::OnceLock;
56///
57/// static CELL: OnceLock<usize> = OnceLock::new();
58///
59/// // `OnceLock` has not been written to yet.
60/// assert!(CELL.get().is_none());
61///
62/// // Spawn a thread and write to `OnceLock`.
63/// std::thread::spawn(|| {
64/// let value = CELL.get_or_init(|| 12345);
65/// assert_eq!(value, &12345);
66/// })
67/// .join()
68/// .unwrap();
69///
70/// // `OnceLock` now contains the value.
71/// assert_eq!(
72/// CELL.get(),
73/// Some(&12345),
74/// );
75/// ```
76#[stable(feature = "once_cell", since = "1.70.0")]
77pub struct OnceLock<T> {
78 once: Once,
79 // Whether or not the value is initialized is tracked by `once.is_completed()`.
80 value: UnsafeCell<MaybeUninit<T>>,
81 /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
82 ///
83 /// ```compile_fail,E0597
84 /// use std::sync::OnceLock;
85 ///
86 /// struct A<'a>(&'a str);
87 ///
88 /// impl<'a> Drop for A<'a> {
89 /// fn drop(&mut self) {}
90 /// }
91 ///
92 /// let cell = OnceLock::new();
93 /// {
94 /// let s = String::new();
95 /// let _ = cell.set(A(&s));
96 /// }
97 /// ```
98 _marker: PhantomData<T>,
99}
100
101impl<T> OnceLock<T> {
102 /// Creates a new empty cell.
103 #[inline]
104 #[must_use]
105 #[stable(feature = "once_cell", since = "1.70.0")]
106 #[rustc_const_stable(feature = "once_cell", since = "1.70.0")]
107 pub const fn new() -> OnceLock<T> {
108 OnceLock {
109 once: Once::new(),
110 value: UnsafeCell::new(MaybeUninit::uninit()),
111 _marker: PhantomData,
112 }
113 }
114
115 /// Gets the reference to the underlying value.
116 ///
117 /// Returns `None` if the cell is empty, or being initialized. This
118 /// method never blocks.
119 #[inline]
120 #[stable(feature = "once_cell", since = "1.70.0")]
121 pub fn get(&self) -> Option<&T> {
122 if self.is_initialized() {
123 // Safe b/c checked is_initialized
124 Some(unsafe { self.get_unchecked() })
125 } else {
126 None
127 }
128 }
129
130 /// Gets the mutable reference to the underlying value.
131 ///
132 /// Returns `None` if the cell is empty. This method never blocks.
133 #[inline]
134 #[stable(feature = "once_cell", since = "1.70.0")]
135 pub fn get_mut(&mut self) -> Option<&mut T> {
136 if self.is_initialized() {
137 // Safe b/c checked is_initialized and we have a unique access
138 Some(unsafe { self.get_unchecked_mut() })
139 } else {
140 None
141 }
142 }
143
144 /// Sets the contents of this cell to `value`.
145 ///
146 /// May block if another thread is currently attempting to initialize the cell. The cell is
147 /// guaranteed to contain a value when set returns, though not necessarily the one provided.
148 ///
149 /// Returns `Ok(())` if the cell's value was set by this call.
150 ///
151 /// # Examples
152 ///
153 /// ```
154 /// use std::sync::OnceLock;
155 ///
156 /// static CELL: OnceLock<i32> = OnceLock::new();
157 ///
158 /// fn main() {
159 /// assert!(CELL.get().is_none());
160 ///
161 /// std::thread::spawn(|| {
162 /// assert_eq!(CELL.set(92), Ok(()));
163 /// }).join().unwrap();
164 ///
165 /// assert_eq!(CELL.set(62), Err(62));
166 /// assert_eq!(CELL.get(), Some(&92));
167 /// }
168 /// ```
169 #[inline]
170 #[stable(feature = "once_cell", since = "1.70.0")]
171 pub fn set(&self, value: T) -> Result<(), T> {
172 match self.try_insert(value) {
173 Ok(_) => Ok(()),
174 Err((_, value)) => Err(value),
175 }
176 }
177
178 /// Sets the contents of this cell to `value` if the cell was empty, then
179 /// returns a reference to it.
180 ///
181 /// May block if another thread is currently attempting to initialize the cell. The cell is
182 /// guaranteed to contain a value when set returns, though not necessarily the one provided.
183 ///
184 /// Returns `Ok(&value)` if the cell was empty and `Err(&current_value, value)` if it was full.
185 ///
186 /// # Examples
187 ///
188 /// ```
189 /// #![feature(once_cell_try_insert)]
190 ///
191 /// use std::sync::OnceLock;
192 ///
193 /// static CELL: OnceLock<i32> = OnceLock::new();
194 ///
195 /// fn main() {
196 /// assert!(CELL.get().is_none());
197 ///
198 /// std::thread::spawn(|| {
199 /// assert_eq!(CELL.try_insert(92), Ok(&92));
200 /// }).join().unwrap();
201 ///
202 /// assert_eq!(CELL.try_insert(62), Err((&92, 62)));
203 /// assert_eq!(CELL.get(), Some(&92));
204 /// }
205 /// ```
206 #[inline]
207 #[unstable(feature = "once_cell_try_insert", issue = "116693")]
208 pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
209 let mut value = Some(value);
210 let res = self.get_or_init(|| value.take().unwrap());
211 match value {
212 None => Ok(res),
213 Some(value) => Err((res, value)),
214 }
215 }
216
217 /// Gets the contents of the cell, initializing it with `f` if the cell
218 /// was empty.
219 ///
220 /// Many threads may call `get_or_init` concurrently with different
221 /// initializing functions, but it is guaranteed that only one function
222 /// will be executed.
223 ///
224 /// # Panics
225 ///
226 /// If `f` panics, the panic is propagated to the caller, and the cell
227 /// remains uninitialized.
228 ///
229 /// It is an error to reentrantly initialize the cell from `f`. The
230 /// exact outcome is unspecified. Current implementation deadlocks, but
231 /// this may be changed to a panic in the future.
232 ///
233 /// # Examples
234 ///
235 /// ```
236 /// use std::sync::OnceLock;
237 ///
238 /// let cell = OnceLock::new();
239 /// let value = cell.get_or_init(|| 92);
240 /// assert_eq!(value, &92);
241 /// let value = cell.get_or_init(|| unreachable!());
242 /// assert_eq!(value, &92);
243 /// ```
244 #[inline]
245 #[stable(feature = "once_cell", since = "1.70.0")]
246 pub fn get_or_init<F>(&self, f: F) -> &T
247 where
248 F: FnOnce() -> T,
249 {
250 match self.get_or_try_init(|| Ok::<T, !>(f())) {
251 Ok(val) => val,
252 }
253 }
254
255 /// Gets the contents of the cell, initializing it with `f` if
256 /// the cell was empty. If the cell was empty and `f` failed, an
257 /// error is returned.
258 ///
259 /// # Panics
260 ///
261 /// If `f` panics, the panic is propagated to the caller, and
262 /// the cell remains uninitialized.
263 ///
264 /// It is an error to reentrantly initialize the cell from `f`.
265 /// The exact outcome is unspecified. Current implementation
266 /// deadlocks, but this may be changed to a panic in the future.
267 ///
268 /// # Examples
269 ///
270 /// ```
271 /// #![feature(once_cell_try)]
272 ///
273 /// use std::sync::OnceLock;
274 ///
275 /// let cell = OnceLock::new();
276 /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
277 /// assert!(cell.get().is_none());
278 /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
279 /// Ok(92)
280 /// });
281 /// assert_eq!(value, Ok(&92));
282 /// assert_eq!(cell.get(), Some(&92))
283 /// ```
284 #[inline]
285 #[unstable(feature = "once_cell_try", issue = "109737")]
286 pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
287 where
288 F: FnOnce() -> Result<T, E>,
289 {
290 // Fast path check
291 // NOTE: We need to perform an acquire on the state in this method
292 // in order to correctly synchronize `LazyLock::force`. This is
293 // currently done by calling `self.get()`, which in turn calls
294 // `self.is_initialized()`, which in turn performs the acquire.
295 if let Some(value) = self.get() {
296 return Ok(value);
297 }
298 self.initialize(f)?;
299
300 debug_assert!(self.is_initialized());
301
302 // SAFETY: The inner value has been initialized
303 Ok(unsafe { self.get_unchecked() })
304 }
305
306 /// Consumes the `OnceLock`, returning the wrapped value. Returns
307 /// `None` if the cell was empty.
308 ///
309 /// # Examples
310 ///
311 /// ```
312 /// use std::sync::OnceLock;
313 ///
314 /// let cell: OnceLock<String> = OnceLock::new();
315 /// assert_eq!(cell.into_inner(), None);
316 ///
317 /// let cell = OnceLock::new();
318 /// cell.set("hello".to_string()).unwrap();
319 /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
320 /// ```
321 #[inline]
322 #[stable(feature = "once_cell", since = "1.70.0")]
323 pub fn into_inner(mut self) -> Option<T> {
324 self.take()
325 }
326
327 /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
328 ///
329 /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized.
330 ///
331 /// Safety is guaranteed by requiring a mutable reference.
332 ///
333 /// # Examples
334 ///
335 /// ```
336 /// use std::sync::OnceLock;
337 ///
338 /// let mut cell: OnceLock<String> = OnceLock::new();
339 /// assert_eq!(cell.take(), None);
340 ///
341 /// let mut cell = OnceLock::new();
342 /// cell.set("hello".to_string()).unwrap();
343 /// assert_eq!(cell.take(), Some("hello".to_string()));
344 /// assert_eq!(cell.get(), None);
345 /// ```
346 #[inline]
347 #[stable(feature = "once_cell", since = "1.70.0")]
348 pub fn take(&mut self) -> Option<T> {
349 if self.is_initialized() {
350 self.once = Once::new();
351 // SAFETY: `self.value` is initialized and contains a valid `T`.
352 // `self.once` is reset, so `is_initialized()` will be false again
353 // which prevents the value from being read twice.
354 unsafe { Some((&mut *self.value.get()).assume_init_read()) }
355 } else {
356 None
357 }
358 }
359
360 #[inline]
361 fn is_initialized(&self) -> bool {
362 self.once.is_completed()
363 }
364
365 #[cold]
366 fn initialize<F, E>(&self, f: F) -> Result<(), E>
367 where
368 F: FnOnce() -> Result<T, E>,
369 {
370 let mut res: Result<(), E> = Ok(());
371 let slot = &self.value;
372
373 // Ignore poisoning from other threads
374 // If another thread panics, then we'll be able to run our closure
375 self.once.call_once_force(|p| {
376 match f() {
377 Ok(value) => {
378 unsafe { (&mut *slot.get()).write(value) };
379 }
380 Err(e) => {
381 res = Err(e);
382
383 // Treat the underlying `Once` as poisoned since we
384 // failed to initialize our value. Calls
385 p.poison();
386 }
387 }
388 });
389 res
390 }
391
392 /// # Safety
393 ///
394 /// The value must be initialized
395 #[inline]
396 unsafe fn get_unchecked(&self) -> &T {
397 debug_assert!(self.is_initialized());
398 (&*self.value.get()).assume_init_ref()
399 }
400
401 /// # Safety
402 ///
403 /// The value must be initialized
404 #[inline]
405 unsafe fn get_unchecked_mut(&mut self) -> &mut T {
406 debug_assert!(self.is_initialized());
407 (&mut *self.value.get()).assume_init_mut()
408 }
409}
410
411// Why do we need `T: Send`?
412// Thread A creates a `OnceLock` and shares it with
413// scoped thread B, which fills the cell, which is
414// then destroyed by A. That is, destructor observes
415// a sent value.
416#[stable(feature = "once_cell", since = "1.70.0")]
417unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
418#[stable(feature = "once_cell", since = "1.70.0")]
419unsafe impl<T: Send> Send for OnceLock<T> {}
420
421#[stable(feature = "once_cell", since = "1.70.0")]
422impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
423#[stable(feature = "once_cell", since = "1.70.0")]
424impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
425
426#[stable(feature = "once_cell", since = "1.70.0")]
427impl<T> Default for OnceLock<T> {
428 /// Creates a new empty cell.
429 ///
430 /// # Example
431 ///
432 /// ```
433 /// use std::sync::OnceLock;
434 ///
435 /// fn main() {
436 /// assert_eq!(OnceLock::<()>::new(), OnceLock::default());
437 /// }
438 /// ```
439 #[inline]
440 fn default() -> OnceLock<T> {
441 OnceLock::new()
442 }
443}
444
445#[stable(feature = "once_cell", since = "1.70.0")]
446impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
447 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448 let mut d: DebugTuple<'_, '_> = f.debug_tuple(name:"OnceLock");
449 match self.get() {
450 Some(v: &T) => d.field(v),
451 None => d.field(&format_args!("<uninit>")),
452 };
453 d.finish()
454 }
455}
456
457#[stable(feature = "once_cell", since = "1.70.0")]
458impl<T: Clone> Clone for OnceLock<T> {
459 #[inline]
460 fn clone(&self) -> OnceLock<T> {
461 let cell: OnceLock = Self::new();
462 if let Some(value: &T) = self.get() {
463 match cell.set(value.clone()) {
464 Ok(()) => (),
465 Err(_) => unreachable!(),
466 }
467 }
468 cell
469 }
470}
471
472#[stable(feature = "once_cell", since = "1.70.0")]
473impl<T> From<T> for OnceLock<T> {
474 /// Create a new cell with its contents set to `value`.
475 ///
476 /// # Example
477 ///
478 /// ```
479 /// use std::sync::OnceLock;
480 ///
481 /// # fn main() -> Result<(), i32> {
482 /// let a = OnceLock::from(3);
483 /// let b = OnceLock::new();
484 /// b.set(3)?;
485 /// assert_eq!(a, b);
486 /// Ok(())
487 /// # }
488 /// ```
489 #[inline]
490 fn from(value: T) -> Self {
491 let cell = Self::new();
492 match cell.set(value) {
493 Ok(()) => cell,
494 Err(_) => unreachable!(),
495 }
496 }
497}
498
499#[stable(feature = "once_cell", since = "1.70.0")]
500impl<T: PartialEq> PartialEq for OnceLock<T> {
501 #[inline]
502 fn eq(&self, other: &OnceLock<T>) -> bool {
503 self.get() == other.get()
504 }
505}
506
507#[stable(feature = "once_cell", since = "1.70.0")]
508impl<T: Eq> Eq for OnceLock<T> {}
509
510#[stable(feature = "once_cell", since = "1.70.0")]
511unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
512 #[inline]
513 fn drop(&mut self) {
514 if self.is_initialized() {
515 // SAFETY: The cell is initialized and being dropped, so it can't
516 // be accessed again. We also don't touch the `T` other than
517 // dropping it, which validates our usage of #[may_dangle].
518 unsafe { (&mut *self.value.get()).assume_init_drop() };
519 }
520 }
521}
522
523#[cfg(test)]
524mod tests;
525