1 | use crate::cell::UnsafeCell; |
2 | use crate::fmt; |
3 | use crate::marker::PhantomData; |
4 | use crate::mem::MaybeUninit; |
5 | use crate::panic::{RefUnwindSafe, UnwindSafe}; |
6 | use 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" )] |
77 | pub 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 | |
101 | impl<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(¤t_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" )] |
417 | unsafe impl<T: Sync + Send> Sync for OnceLock<T> {} |
418 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
419 | unsafe impl<T: Send> Send for OnceLock<T> {} |
420 | |
421 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
422 | impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {} |
423 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
424 | impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {} |
425 | |
426 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
427 | impl<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" )] |
446 | impl<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" )] |
458 | impl<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" )] |
473 | impl<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" )] |
500 | impl<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" )] |
508 | impl<T: Eq> Eq for OnceLock<T> {} |
509 | |
510 | #[stable (feature = "once_cell" , since = "1.70.0" )] |
511 | unsafe 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)] |
524 | mod tests; |
525 | |