poly_once/
once.rs

1//! Standard once cell for one-time initialization.
2//!
3//! This module provides the [`Once<T>`] type, a thread-safe cell that can be
4//! written to exactly once. It's useful for lazy initialization of global state,
5//! caching expensive computations, or any scenario where you need to ensure
6//! initialization happens exactly once across multiple threads.
7//!
8//! The implementation uses atomic operations for the fast path (checking if
9//! initialized) and futex-based synchronization for the slow path (waiting
10//! for initialization to complete).
11
12use core::cell::UnsafeCell;
13use core::future::Future;
14use core::sync::atomic::Ordering;
15use core::{fmt, mem};
16
17use super::state::OnceLock;
18
19/// A thread-safe cell which can be written to only once.
20///
21/// This structure provides safe initialization for values that might be accessed
22/// concurrently by multiple threads. It ensures that the initialization logic
23/// runs only once, even if multiple threads attempt to initialize the value simultaneously.
24///
25/// It uses atomic operations and `parking_lot`'s futex-based synchronization for
26/// efficient blocking when necessary.
27pub struct Once<T> {
28   value: UnsafeCell<mem::MaybeUninit<T>>,
29   lock: OnceLock,
30}
31
32impl<T> Once<T> {
33   /// Creates a new, uninitialized `Once` cell.
34   #[inline]
35   #[must_use]
36   pub const fn new() -> Self {
37      Self {
38         lock: OnceLock::new(),
39         value: UnsafeCell::new(mem::MaybeUninit::uninit()),
40      }
41   }
42
43   /// Creates a new `Once` cell that is already initialized with the given value.
44   #[inline]
45   #[must_use]
46   pub const fn with_value(value: T) -> Self {
47      Self {
48         lock: OnceLock::done(),
49         value: UnsafeCell::new(mem::MaybeUninit::new(value)),
50      }
51   }
52
53   /// Checks if the cell has been initialized.
54   ///
55   /// This method never blocks.
56   #[inline]
57   pub fn is_done(&self) -> bool {
58      self.lock.is_done(Ordering::Relaxed)
59   }
60
61   /// Returns a reference to the contained value if initialized.
62   ///
63   /// Returns `None` if the cell is uninitialized or currently being initialized.
64   /// This method never blocks.
65   #[inline]
66   pub fn get(&self) -> Option<&T> {
67      if self.is_done() {
68         // SAFETY: is_done() returned true, so the value is initialized.
69         Some(unsafe { self.get_unchecked() })
70      } else {
71         None
72      }
73   }
74
75   /// Returns a mutable reference to the contained value if initialized.
76   ///
77   /// Returns `None` if the cell is uninitialized or currently being initialized.
78   /// This method requires exclusive access (`&mut self`) and never blocks.
79   #[inline]
80   pub fn get_mut(&mut self) -> Option<&mut T> {
81      if self.is_done() {
82         // SAFETY: is_done() returned true and we have exclusive access (`&mut self`).
83         Some(unsafe { self.get_unchecked_mut() })
84      } else {
85         None
86      }
87   }
88
89   /// Attempts to initialize the cell with `value` without blocking.
90   ///
91   /// - If the cell is uninitialized and not locked, initializes it with `value` and returns `Ok(&value)`.
92   /// - If the cell is already initialized, returns `Err(value)`.
93   /// - If the cell is currently locked by another thread, returns `Err(value)`.
94   #[inline]
95   pub fn try_set(&self, value: T) -> Result<&T, T> {
96      let Some(guard) = self.lock.try_lock() else {
97         return Err(value);
98      };
99      // SAFETY: We hold the lock, so we have exclusive access to initialize the value.
100      let refv = unsafe { (*self.value.get()).write(value) };
101      guard.commit();
102      Ok(refv)
103   }
104
105   /// Replaces the cell's value, returning the old value if initialized.
106   ///
107   /// - If uninitialized, sets the value to `value` and returns `None`.
108   /// - If initialized, replaces the existing value with `value` and returns the old value.
109   ///
110   /// Requires exclusive access (`&mut self`), so it never blocks.
111   #[inline]
112   pub fn replace_mut(&mut self, value: T) -> Option<T> {
113      let mref = self.value.get_mut();
114
115      if self.lock.set_done() {
116         // Was uninitialized, now set to done. Write the new value.
117         mref.write(value);
118         None
119      } else {
120         // Was already initialized. Replace the existing value.
121         // SAFETY: We have exclusive access and the cell is initialized.
122         let old_value = unsafe { mref.assume_init_mut() };
123         Some(mem::replace(old_value, value))
124      }
125   }
126
127   /// Gets a mutable reference, initializing with `value` if needed.
128   ///
129   /// - If initialized, returns a mutable reference to the existing value.
130   /// - If uninitialized, initializes it with `value` and returns a mutable reference.
131   ///
132   /// Requires exclusive access (`&mut self`), so it never blocks.
133   #[inline]
134   pub fn get_mut_or_set(&mut self, value: T) -> &mut T {
135      if self.lock.set_done() {
136         // Was uninitialized, now set to done. Write the new value.
137         self.value.get_mut().write(value);
138      }
139      // SAFETY: The cell is guaranteed to be initialized here, either previously
140      // or by the call above, and we have exclusive access.
141      unsafe { self.get_unchecked_mut() }
142   }
143
144   /// Gets a mutable reference, initializing with `Default::default()` if needed.
145   ///
146   /// - If initialized, returns a mutable reference to the existing value.
147   /// - If uninitialized, initializes it with `T::default()` and returns a mutable reference.
148   ///
149   /// Requires exclusive access (`&mut self`), so it never blocks.
150   #[inline]
151   pub fn get_mut_or_default(&mut self) -> &mut T
152   where
153      T: Default,
154   {
155      if self.lock.set_done() {
156         // Was uninitialized, now set to done. Write the default value.
157         self.value.get_mut().write(T::default());
158      }
159      // SAFETY: The cell is guaranteed to be initialized here, either previously
160      // or by the call above, and we have exclusive access.
161      unsafe { self.get_unchecked_mut() }
162   }
163
164   /// Returns a reference to the value without checking if it's initialized.
165   ///
166   /// # Safety
167   ///
168   /// Calling this method on an uninitialized `Once` cell is *undefined behavior*.
169   /// The caller must ensure the cell is initialized, e.g., by calling `is_done()` or `get()`.
170   #[inline]
171   pub unsafe fn get_unchecked(&self) -> &T {
172      debug_assert!(self.is_done(), "get_unchecked called on uninitialized Once");
173      // SAFETY: The caller guarantees that the cell is initialized.
174      (*self.value.get()).assume_init_ref()
175   }
176
177   /// Returns a mutable reference to the value without checking if it's initialized.
178   ///
179   /// # Safety
180   ///
181   /// Calling this method on an uninitialized `Once` cell is *undefined behavior*.
182   /// The caller must ensure the cell is initialized and that they have exclusive access.
183   #[inline]
184   pub unsafe fn get_unchecked_mut(&mut self) -> &mut T {
185      debug_assert!(
186         self.is_done(),
187         "get_unchecked_mut called on uninitialized Once"
188      );
189      // SAFETY: The caller guarantees that the cell is initialized and we have exclusive access.
190      unsafe { (*self.value.get()).assume_init_mut() }
191   }
192
193   /// Takes the value out of the cell, leaving it uninitialized.
194   ///
195   /// Returns `Some(value)` if the cell was initialized, `None` otherwise.
196   /// Requires exclusive access (`&mut self`), so it never blocks.
197   #[inline]
198   pub fn take(&mut self) -> Option<T> {
199      if self.lock.set_uninit() {
200         // Was initialized, now set to uninit. Read the value out.
201         // SAFETY: The cell was initialized (guaranteed by set_uninit returning true).
202         // The state is now uninitialized, preventing further reads of the old value.
203         // We have exclusive access.
204         unsafe { Some((*self.value.get()).assume_init_read()) }
205      } else {
206         // Was already uninitialized.
207         None
208      }
209   }
210
211   /// Initializes the cell with `value`. Blocks if another thread is initializing.
212   ///
213   /// - If uninitialized, initializes it with `value` and returns `Ok(())`.
214   /// - If already initialized, returns `Err(value)`.
215   ///
216   /// Guarantees the cell is initialized upon return, but not necessarily with `value`
217   /// if another thread completed initialization first.
218   #[inline]
219   pub fn set(&self, value: T) -> Result<(), T> {
220      match self.try_insert(value) {
221         Ok(_) => Ok(()), // Successfully inserted our value
222         Err((_current_value, original_value)) => Err(original_value), // Already initialized by someone else
223      }
224   }
225
226   /// Initializes the cell with `value` if uninitialized, returning a reference. Blocks if needed.
227   ///
228   /// - If uninitialized, initializes with `value` and returns `Ok(&value)`.
229   /// - If already initialized, returns `Err((&current_value, value))`.
230   ///
231   /// Guarantees the cell is initialized upon return.
232   #[inline]
233   pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
234      // `get_or_init` ensures initialization. We use `value` only if the cell was empty.
235      let mut value_opt = Some(value);
236      let res_ref = self.get_or_init(|| value_opt.take().unwrap());
237      match value_opt {
238         None => Ok(res_ref), // Our value was used for initialization
239         Some(original_value) => Err((res_ref, original_value)), // Someone else initialized it first
240      }
241   }
242
243   /// Gets the value, initializing with `f()` if needed. Blocks if needed.
244   ///
245   /// - If initialized, returns a reference to the existing value.
246   /// - If uninitialized, calls `f()`, stores the result, and returns a reference.
247   ///
248   /// If multiple threads call this concurrently, only one `f()` execution happens.
249   #[inline]
250   pub fn get_or_init<F>(&self, f: F) -> &T
251   where
252      F: FnOnce() -> T,
253   {
254      if let Some(value) = self.get() {
255         return value;
256      }
257      // Cold path: needs initialization
258      self.initialize(f);
259      // SAFETY: initialize ensures the value is now initialized.
260      unsafe { self.get_unchecked() }
261   }
262
263   /// Gets a mutable reference, initializing with `f()` if needed.
264   ///
265   /// - If initialized, returns a mutable reference to the existing value.
266   /// - If uninitialized, calls `f()`, stores the result, and returns a mutable reference.
267   ///
268   /// Requires exclusive access (`&mut self`), so it never blocks.
269   #[inline]
270   pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
271   where
272      F: FnOnce() -> T,
273   {
274      if self.is_done() {
275         // Already initialized.
276      } else if let Some(guard) = self.lock.try_lock() {
277         // We got the lock (because is_done was false and no one else had it). Initialize it.
278         // SAFETY: We hold the lock, exclusive access to initialize.
279         unsafe { (*self.value.get()).write(f()) };
280         guard.commit();
281      } else {
282         // This case should theoretically not happen with &mut self,
283         // as try_lock should succeed if !is_done().
284         // If it did, it implies a logic error or unexpected concurrent access.
285         unreachable!("Could not lock for init despite having exclusive access");
286      }
287
288      // SAFETY: The cell is guaranteed to be initialized now, and we have exclusive access.
289      unsafe { self.get_unchecked_mut() }
290   }
291
292   /// Gets the value, initializing with fallible `f()` if needed. Blocks if needed.
293   ///
294   /// - If initialized, returns `Ok(&value)`.
295   /// - If uninitialized, calls `f()`:
296   ///     - On `Ok(value)`, initializes the cell and returns `Ok(&value)`.
297   ///     - On `Err(e)`, returns `Err(e)` and leaves the cell uninitialized.
298   ///
299   /// If multiple threads call this concurrently, only one `f()` execution happens.
300   pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
301   where
302      F: FnOnce() -> Result<T, E>,
303   {
304      if let Some(value) = self.get() {
305         return Ok(value);
306      }
307      // Cold path: needs initialization attempt
308      self.try_initialize(f)?;
309      // If try_initialize succeeded, it's now initialized.
310      debug_assert!(self.is_done());
311      // SAFETY: try_initialize succeeded, so the value is initialized.
312      Ok(unsafe { self.get_unchecked() })
313   }
314
315   /// Gets a mutable reference, initializing with fallible `f()` if needed.
316   ///
317   /// - If initialized, returns `Ok(&mut value)`.
318   /// - If uninitialized, calls `f()`:
319   ///     - On `Ok(value)`, initializes the cell and returns `Ok(&mut value)`.
320   ///     - On `Err(e)`, returns `Err(e)` and leaves the cell uninitialized.
321   ///
322   /// Requires exclusive access (`&mut self`), so it never blocks (initialization happens inline).
323   pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
324   where
325      F: FnOnce() -> Result<T, E>,
326   {
327      if let Some(guard) = self.lock.try_lock() {
328         // We got the lock. Try to initialize.
329         self.value.get_mut().write(f()?);
330         guard.commit();
331      }
332      // SAFETY: The cell is guaranteed to be initialized now (or we returned Err),
333      // and we have exclusive access.
334      Ok(unsafe { self.get_unchecked_mut() })
335   }
336
337   /// Gets the value, initializing asynchronously with `f()` if needed. Blocks if needed.
338   ///
339   /// - If initialized, returns a reference to the existing value.
340   /// - If uninitialized, awaits `f()`, stores the result, and returns a reference.
341   ///
342   /// If multiple tasks call this concurrently, only one `f()` execution happens.
343   #[inline]
344   pub async fn get_or_init_async<F, Fut>(&self, f: F) -> &T
345   where
346      F: FnOnce() -> Fut,
347      Fut: Future<Output = T>,
348   {
349      if let Some(value) = self.get() {
350         return value;
351      }
352      // Cold path: needs async initialization
353      self.initialize_async(f).await;
354      // SAFETY: initialize_async ensures the value is now initialized.
355      unsafe { self.get_unchecked() }
356   }
357
358   /// Gets a mutable reference, initializing asynchronously with `f()` if needed.
359   ///
360   /// - If initialized, returns a mutable reference to the existing value.
361   /// - If uninitialized, awaits `f()`, stores the result, and returns a mutable reference.
362   ///
363   /// Requires exclusive access (`&mut self`), so it never blocks (initialization happens inline).
364   #[inline]
365   pub async fn get_mut_or_init_async<F, Fut>(&mut self, f: F) -> &mut T
366   where
367      F: FnOnce() -> Fut,
368      Fut: Future<Output = T>,
369   {
370      if let Some(guard) = self.lock.try_lock() {
371         // We got the lock. Try to initialize.
372         self.value.get_mut().write(f().await);
373         guard.commit();
374      }
375      // SAFETY: The cell is guaranteed to be initialized now (or we returned Err),
376      // and we have exclusive access.
377      unsafe { self.get_unchecked_mut() }
378   }
379
380   /// Gets the value, initializing asynchronously with fallible `f()` if needed. Blocks if needed.
381   ///
382   /// - If initialized, returns `Ok(&value)`.
383   /// - If uninitialized, awaits `f()`:
384   ///     - On `Ok(value)`, initializes the cell and returns `Ok(&value)`.
385   ///     - On `Err(e)`, returns `Err(e)` and leaves the cell uninitialized.
386   ///
387   /// If multiple tasks call this concurrently, only one `f()` execution happens.
388   pub async fn get_or_try_init_async<F, Fut, E>(&self, f: F) -> Result<&T, E>
389   where
390      F: FnOnce() -> Fut,
391      Fut: Future<Output = Result<T, E>>,
392   {
393      if let Some(value) = self.get() {
394         return Ok(value);
395      }
396      // Cold path: needs async initialization attempt
397      self.try_initialize_async(f).await?;
398      // If try_initialize_async succeeded, it's now initialized.
399      debug_assert!(self.is_done());
400      // SAFETY: try_initialize_async succeeded, so the value is initialized.
401      Ok(unsafe { self.get_unchecked() })
402   }
403
404   /// Gets a mutable reference, initializing asynchronously with fallible `f()` if needed.
405   ///
406   /// - If initialized, returns `Ok(&mut value)`.
407   /// - If uninitialized, awaits `f()`:
408   ///     - On `Ok(value)`, initializes the cell and returns `Ok(&mut value)`.
409   ///     - On `Err(e)`, returns `Err(e)` and leaves the cell uninitialized.
410   ///
411   /// Requires exclusive access (`&mut self`), so it never blocks (initialization happens inline).
412   pub async fn get_mut_or_try_init_async<F, Fut, E>(&mut self, f: F) -> Result<&mut T, E>
413   where
414      F: FnOnce() -> Fut,
415      Fut: Future<Output = Result<T, E>>,
416   {
417      if let Some(guard) = self.lock.try_lock() {
418         // We got the lock. Try to initialize.
419         self.value.get_mut().write(f().await?);
420         guard.commit();
421      }
422
423      // SAFETY: The cell is guaranteed to be initialized now (or we returned Err),
424      // and we have exclusive access.
425      Ok(unsafe { self.get_unchecked_mut() })
426   }
427
428   // --- Internal Initialization Helpers ---
429
430   /// Cold path for `get_or_init_async`. Acquires lock asynchronously and awaits initializer.
431   #[cold]
432   async fn initialize_async<F, Fut>(&self, f: F)
433   where
434      F: FnOnce() -> Fut,
435      Fut: Future<Output = T>,
436   {
437      let Some(guard) = self.lock.lock_async().await else {
438         return; // Another task initialized it while we waited
439      };
440      // SAFETY: We hold the lock, exclusive access to initialize the value.
441      unsafe { (*self.value.get()).write(f().await) };
442      guard.commit(); // Mark as done and notify waiters
443   }
444
445   /// Cold path for `get_or_try_init_async`. Acquires lock asynchronously and awaits fallible initializer.
446   #[cold]
447   async fn try_initialize_async<Fn, Fut, E>(&self, f: Fn) -> Result<(), E>
448   where
449      Fn: FnOnce() -> Fut,
450      Fut: Future<Output = Result<T, E>>,
451   {
452      let Some(guard) = self.lock.lock_async().await else {
453         return Ok(()); // Another task initialized it while we waited
454      };
455      let value = f().await?; // Await initializer. If it fails, guard is dropped, state reset.
456                              // SAFETY: We hold the lock, exclusive access to initialize the value.
457      unsafe { (*self.value.get()).write(value) };
458      guard.commit(); // Mark as done and notify waiters
459      Ok(())
460   }
461
462   /// Cold path for `get_or_init`. Acquires lock and calls initializer.
463   #[cold]
464   fn initialize<F>(&self, f: F)
465   where
466      F: FnOnce() -> T,
467   {
468      let Some(guard) = self.lock.lock() else {
469         return; // Another thread initialized it while we waited for the lock
470      };
471      // SAFETY: We hold the lock, exclusive access to initialize the value.
472      unsafe { (*self.value.get()).write(f()) };
473      guard.commit(); // Mark as done and notify waiters
474   }
475
476   /// Cold path for `get_or_try_init`. Acquires lock and calls fallible initializer.
477   #[cold]
478   fn try_initialize<F, E>(&self, f: F) -> Result<(), E>
479   where
480      F: FnOnce() -> Result<T, E>,
481   {
482      let Some(guard) = self.lock.lock() else {
483         return Ok(()); // Another thread initialized it while we waited for the lock
484      };
485      let value = f()?; // Call initializer. If it fails, guard is dropped, state reset.
486                        // SAFETY: We hold the lock, exclusive access to initialize the value.
487      unsafe { (*self.value.get()).write(value) };
488      guard.commit(); // Mark as done and notify waiters
489      Ok(())
490   }
491}
492
493// --- Trait Implementations ---
494
495impl<T> From<Option<T>> for Once<T> {
496   /// Creates an initialized `Once` from `Some(value)` or an uninitialized one from `None`.
497   fn from(value: Option<T>) -> Self {
498      match value {
499         Some(value) => Self::with_value(value),
500         None => Self::new(),
501      }
502   }
503}
504
505// SAFETY:
506// `&Once<T>` is `Sync` if `&T` is `Sync` (requiring `T: Sync`)
507// and if the initialization mechanism is thread-safe (which it is).
508// `T: Send` is also required because a value provided by one thread
509// might be read or dropped by another.
510unsafe impl<T: Sync + Send> Sync for Once<T> {}
511// SAFETY:
512// `Once<T>` is `Send` if `T` is `Send`, as the ownership of `T`
513// can be transferred across threads via initialization or `take()`.
514unsafe impl<T: Send> Send for Once<T> {}
515
516impl<T> Default for Once<T> {
517   /// Creates a new, uninitialized `Once` cell.
518   #[inline]
519   fn default() -> Self {
520      Self::new()
521   }
522}
523
524impl<T: fmt::Display> fmt::Display for Once<T> {
525   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526      match self.get() {
527         Some(v) => fmt::Display::fmt(v, f),
528         None => f.write_str("<uninit>"),
529      }
530   }
531}
532
533impl<T: fmt::Debug> fmt::Debug for Once<T> {
534   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
535      let mut d = f.debug_tuple("Once");
536      match self.get() {
537         Some(v) => d.field(v),
538         None => d.field(&format_args!("<uninit>")),
539      };
540      d.finish()
541   }
542}
543
544impl<T: Clone> Clone for Once<T> {
545   /// Clones the `Once` cell.
546   ///
547   /// If the original cell is initialized, the clone will be initialized
548   /// with a cloned value. If the original is uninitialized, the clone
549   /// will also be uninitialized.
550   #[inline]
551   fn clone(&self) -> Self {
552      match self.get() {
553         Some(value) => Self::with_value(value.clone()),
554         None => Self::new(),
555      }
556   }
557}
558
559impl<T> From<T> for Once<T> {
560   /// Creates a new, initialized `Once` cell from the given value.
561   #[inline]
562   fn from(value: T) -> Self {
563      Self::with_value(value)
564   }
565}
566
567impl<T: PartialEq> PartialEq for Once<T> {
568   /// Checks if two `Once` cells are equal.
569   ///
570   /// They are equal if both are uninitialized, or if both are initialized
571   /// and their contained values are equal according to `PartialEq`.
572   #[inline]
573   fn eq(&self, other: &Self) -> bool {
574      self.get() == other.get()
575   }
576}
577
578impl<T: Eq> Eq for Once<T> {}
579
580impl<T> Drop for Once<T> {
581   #[inline]
582   fn drop(&mut self) {
583      if self.is_done() {
584         // The state indicates the cell is initialized.
585         // SAFETY: We have exclusive access (`&mut self`), the cell is initialized,
586         // and we are dropping it, so the value won't be accessed again.
587         unsafe { self.value.get_mut().assume_init_drop() };
588      }
589   }
590}