generic_once_cell/
lib.rs

1//! # Overview
2//!
3//! generic_once_cell is a generic `no_std` version of [once_cell].
4//! Internal synchronization for initialization is provided as type parameter via custom mutexes based on [lock_api].
5//! This makes it suitable for use in complex `no_std` scenarios where [once_cell's `critical-section` support] and [`once_cell::race`] are not sufficient.
6//!
7//! The core API looks *roughly* like this:
8//! ```rust,ignore
9//! impl<R: lock_api::RawMutex, T> OnceCell<R, T> {
10//!     const fn new() -> Self { ... }
11//!     fn set(&self, value: T) -> Result<(), T> { ... }
12//!     fn get(&self) -> Option<&T> { ... }
13//! }
14//! ```
15//!
16//! # API
17//!
18//! Apart from the generic type parameter, this crate has exactly [once_cell]'s API.
19//!
20//! # Mutex implementations
21//!
22//! You can plug in any implementation of [`lock_api::RawMutex`].
23//!
24//! Different usable mutex implementations are available in crates:
25//! * [spinning-top] from Rust OSDev.
26//! * [spin], though you might prefer [`spin::once::Once`] and [`spin::lazy::Lazy`].
27//! * [parking_lot], though you might prefer the original [once_cell].
28//!
29//! This crate shows its real strength when using custom, specialized mutex implementations though.
30//!
31//! # Performance
32//!
33//! The mutex is only used for initialization.
34//! Once initialized, the overhead for each access is to check an `AtomicBool`.
35//!
36//! [once_cell]: https://crates.io/crates/once_cell
37//! [lock_api]: https://crates.io/crates/lock_api
38//! [once_cell's `critical-section` support]: https://github.com/matklad/once_cell/blob/master/CHANGELOG.md#1160
39//! [`once_cell::race`]: https://docs.rs/once_cell/1.16.0/once_cell/race/index.html
40//! [spinning-top]: https://crates.io/crates/spinning_top
41//! [spin]: https://crates.io/crates/spin
42//! [`spin::once::Once`]: https://docs.rs/spin/0.9.4/spin/once/struct.Once.html
43//! [`spin::lazy::Lazy`]: https://docs.rs/spin/0.9.4/spin/lazy/struct.Lazy.html
44//! [parking_lot]: https://crates.io/crates/parking_lot
45
46#![no_std]
47#![warn(unsafe_op_in_unsafe_fn)]
48
49mod imp;
50
51use core::{
52    cell::Cell,
53    fmt, mem,
54    ops::{Deref, DerefMut},
55    panic::RefUnwindSafe,
56};
57
58use imp::OnceCell as Imp;
59use lock_api::RawMutex;
60
61/// A thread-safe cell which can be written to only once.
62///
63/// `OnceCell` provides `&` references to the contents without RAII guards.
64///
65/// Reading a non-`None` value out of `OnceCell` establishes a
66/// happens-before relationship with a corresponding write. For example, if
67/// thread A initializes the cell with `get_or_init(f)`, and thread B
68/// subsequently reads the result of this call, B also observes all the side
69/// effects of `f`.
70///
71/// # Example
72/// ```
73/// # use parking_lot::RawMutex;
74/// use generic_once_cell::OnceCell;
75///
76/// static CELL: OnceCell<RawMutex, String> = OnceCell::new();
77/// assert!(CELL.get().is_none());
78///
79/// std::thread::spawn(|| {
80///     let value: &String = CELL.get_or_init(|| {
81///         "Hello, World!".to_string()
82///     });
83///     assert_eq!(value, "Hello, World!");
84/// }).join().unwrap();
85///
86/// let value: Option<&String> = CELL.get();
87/// assert!(value.is_some());
88/// assert_eq!(value.unwrap().as_str(), "Hello, World!");
89/// ```
90pub struct OnceCell<R, T>(Imp<R, T>);
91
92impl<R: RawMutex, T> Default for OnceCell<R, T> {
93    fn default() -> Self {
94        Self::new()
95    }
96}
97
98impl<R: RawMutex, T: fmt::Debug> fmt::Debug for OnceCell<R, T> {
99    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100        match self.get() {
101            Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
102            None => f.write_str("OnceCell(Uninit)"),
103        }
104    }
105}
106
107impl<R: RawMutex, T: Clone> Clone for OnceCell<R, T> {
108    fn clone(&self) -> Self {
109        match self.get() {
110            Some(value) => Self::with_value(value.clone()),
111            None => Self::new(),
112        }
113    }
114
115    fn clone_from(&mut self, source: &Self) {
116        match (self.get_mut(), source.get()) {
117            (Some(this), Some(source)) => this.clone_from(source),
118            _ => *self = source.clone(),
119        }
120    }
121}
122
123impl<R: RawMutex, T> From<T> for OnceCell<R, T> {
124    fn from(value: T) -> Self {
125        Self::with_value(value)
126    }
127}
128
129impl<R: RawMutex, T: PartialEq> PartialEq for OnceCell<R, T> {
130    fn eq(&self, other: &Self) -> bool {
131        self.get() == other.get()
132    }
133}
134
135impl<R: RawMutex, T: Eq> Eq for OnceCell<R, T> {}
136
137impl<R: RawMutex, T> OnceCell<R, T> {
138    /// Creates a new empty cell.
139    pub const fn new() -> Self {
140        Self(Imp::new())
141    }
142
143    /// Creates a new initialized cell.
144    pub const fn with_value(value: T) -> Self {
145        Self(Imp::with_value(value))
146    }
147
148    /// Gets the reference to the underlying value.
149    ///
150    /// Returns `None` if the cell is empty, or being initialized. This
151    /// method never blocks.
152    pub fn get(&self) -> Option<&T> {
153        if self.0.is_initialized() {
154            // Safe b/c value is initialized.
155            Some(unsafe { self.get_unchecked() })
156        } else {
157            None
158        }
159    }
160
161    /// Gets the mutable reference to the underlying value.
162    ///
163    /// Returns `None` if the cell is empty.
164    ///
165    /// This method is allowed to violate the invariant of writing to a `OnceCell`
166    /// at most once because it requires `&mut` access to `self`. As with all
167    /// interior mutability, `&mut` access permits arbitrary modification:
168    ///
169    /// ```
170    /// # use parking_lot::RawMutex;
171    /// use generic_once_cell::OnceCell;
172    ///
173    /// let mut cell: OnceCell<RawMutex, u32> = OnceCell::new();
174    /// cell.set(92).unwrap();
175    /// cell = OnceCell::new();
176    /// ```
177    #[inline]
178    pub fn get_mut(&mut self) -> Option<&mut T> {
179        self.0.get_mut()
180    }
181
182    /// Get the reference to the underlying value, without checking if the
183    /// cell is initialized.
184    ///
185    /// # Safety
186    ///
187    /// Caller must ensure that the cell is in initialized state, and that
188    /// the contents are acquired by (synchronized to) this thread.
189    #[inline]
190    pub unsafe fn get_unchecked(&self) -> &T {
191        // SAFETY: The caller ensures that the value is initialized and access synchronized.
192        unsafe { self.0.get_unchecked() }
193    }
194
195    /// Sets the contents of this cell to `value`.
196    ///
197    /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
198    /// full.
199    ///
200    /// # Example
201    ///
202    /// ```
203    /// # use parking_lot::RawMutex;
204    /// use generic_once_cell::OnceCell;
205    ///
206    /// static CELL: OnceCell<RawMutex, i32> = OnceCell::new();
207    ///
208    /// fn main() {
209    ///     assert!(CELL.get().is_none());
210    ///
211    ///     std::thread::spawn(|| {
212    ///         assert_eq!(CELL.set(92), Ok(()));
213    ///     }).join().unwrap();
214    ///
215    ///     assert_eq!(CELL.set(62), Err(62));
216    ///     assert_eq!(CELL.get(), Some(&92));
217    /// }
218    /// ```
219    pub fn set(&self, value: T) -> Result<(), T> {
220        match self.try_insert(value) {
221            Ok(_) => Ok(()),
222            Err((_, value)) => Err(value),
223        }
224    }
225
226    /// Like [`set`](Self::set), but also returns a reference to the final cell value.
227    ///
228    /// # Example
229    ///
230    /// ```
231    /// # use parking_lot::RawMutex;
232    /// use generic_once_cell::OnceCell;
233    ///
234    /// let cell = OnceCell::<RawMutex, _>::new();
235    /// assert!(cell.get().is_none());
236    ///
237    /// assert_eq!(cell.try_insert(92), Ok(&92));
238    /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
239    ///
240    /// assert!(cell.get().is_some());
241    /// ```
242    pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
243        let mut value = Some(value);
244        let res = self.get_or_init(|| unsafe { value.take().unwrap_unchecked() });
245        match value {
246            None => Ok(res),
247            Some(value) => Err((res, value)),
248        }
249    }
250
251    /// Gets the contents of the cell, initializing it with `f` if the cell
252    /// was empty.
253    ///
254    /// Many threads may call `get_or_init` concurrently with different
255    /// initializing functions, but it is guaranteed that only one function
256    /// will be executed.
257    ///
258    /// # Panics
259    ///
260    /// If `f` panics, the panic is propagated to the caller, and the cell
261    /// remains uninitialized.
262    ///
263    /// It is an error to reentrantly initialize the cell from `f`. The
264    /// exact outcome is unspecified. Current implementation deadlocks, but
265    /// this may be changed to a panic in the future.
266    ///
267    /// # Example
268    /// ```
269    /// # use parking_lot::RawMutex;
270    /// use generic_once_cell::OnceCell;
271    ///
272    /// let cell = OnceCell::<RawMutex, _>::new();
273    /// let value = cell.get_or_init(|| 92);
274    /// assert_eq!(value, &92);
275    /// let value = cell.get_or_init(|| unreachable!());
276    /// assert_eq!(value, &92);
277    /// ```
278    pub fn get_or_init<F>(&self, f: F) -> &T
279    where
280        F: FnOnce() -> T,
281    {
282        enum Void {}
283        match self.get_or_try_init(|| Ok::<T, Void>(f())) {
284            Ok(val) => val,
285            Err(void) => match void {},
286        }
287    }
288
289    /// Gets the contents of the cell, initializing it with `f` if
290    /// the cell was empty. If the cell was empty and `f` failed, an
291    /// error is returned.
292    ///
293    /// # Panics
294    ///
295    /// If `f` panics, the panic is propagated to the caller, and
296    /// the cell remains uninitialized.
297    ///
298    /// It is an error to reentrantly initialize the cell from `f`.
299    /// The exact outcome is unspecified. Current implementation
300    /// deadlocks, but this may be changed to a panic in the future.
301    ///
302    /// # Example
303    /// ```
304    /// # use parking_lot::RawMutex;
305    /// use generic_once_cell::OnceCell;
306    ///
307    /// let cell = OnceCell::<RawMutex, _>::new();
308    /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
309    /// assert!(cell.get().is_none());
310    /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
311    ///     Ok(92)
312    /// });
313    /// assert_eq!(value, Ok(&92));
314    /// assert_eq!(cell.get(), Some(&92))
315    /// ```
316    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
317    where
318        F: FnOnce() -> Result<T, E>,
319    {
320        // Fast path check
321        if let Some(value) = self.get() {
322            return Ok(value);
323        }
324
325        self.0.initialize(f)?;
326
327        // Safe b/c value is initialized.
328        debug_assert!(self.0.is_initialized());
329        Ok(unsafe { self.get_unchecked() })
330    }
331
332    /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
333    ///
334    /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
335    ///
336    /// # Examples
337    ///
338    /// ```
339    /// # use parking_lot::RawMutex;
340    /// use generic_once_cell::OnceCell;
341    ///
342    /// let mut cell: OnceCell<RawMutex, String> = OnceCell::new();
343    /// assert_eq!(cell.take(), None);
344    ///
345    /// let mut cell = OnceCell::<RawMutex, _>::new();
346    /// cell.set("hello".to_string()).unwrap();
347    /// assert_eq!(cell.take(), Some("hello".to_string()));
348    /// assert_eq!(cell.get(), None);
349    /// ```
350    ///
351    /// This method is allowed to violate the invariant of writing to a `OnceCell`
352    /// at most once because it requires `&mut` access to `self`. As with all
353    /// interior mutability, `&mut` access permits arbitrary modification:
354    ///
355    /// ```
356    /// # use parking_lot::RawMutex;
357    /// use generic_once_cell::OnceCell;
358    ///
359    /// let mut cell: OnceCell<RawMutex, u32> = OnceCell::new();
360    /// cell.set(92).unwrap();
361    /// cell = OnceCell::new();
362    /// ```
363    pub fn take(&mut self) -> Option<T> {
364        mem::take(self).into_inner()
365    }
366
367    /// Consumes the `OnceCell`, returning the wrapped value. Returns
368    /// `None` if the cell was empty.
369    ///
370    /// # Examples
371    ///
372    /// ```
373    /// # use parking_lot::RawMutex;
374    /// use generic_once_cell::OnceCell;
375    ///
376    /// let cell: OnceCell<RawMutex, String> = OnceCell::new();
377    /// assert_eq!(cell.into_inner(), None);
378    ///
379    /// let cell = OnceCell::<RawMutex, _>::new();
380    /// cell.set("hello".to_string()).unwrap();
381    /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
382    /// ```
383    #[inline]
384    pub fn into_inner(self) -> Option<T> {
385        self.0.into_inner()
386    }
387}
388
389/// A value which is initialized on the first access.
390///
391/// This type is thread-safe and can be used in statics.
392///
393/// # Example
394///
395/// ```
396/// # use parking_lot::RawMutex;
397/// use std::collections::HashMap;
398///
399/// use generic_once_cell::Lazy;
400///
401/// static HASHMAP: Lazy<RawMutex, HashMap<i32, String>> = Lazy::new(|| {
402///     println!("initializing");
403///     let mut m = HashMap::new();
404///     m.insert(13, "Spica".to_string());
405///     m.insert(74, "Hoyten".to_string());
406///     m
407/// });
408///
409/// fn main() {
410///     println!("ready");
411///     std::thread::spawn(|| {
412///         println!("{:?}", HASHMAP.get(&13));
413///     }).join().unwrap();
414///     println!("{:?}", HASHMAP.get(&74));
415///
416///     // Prints:
417///     //   ready
418///     //   initializing
419///     //   Some("Spica")
420///     //   Some("Hoyten")
421/// }
422/// ```
423pub struct Lazy<R, T, F = fn() -> T> {
424    cell: OnceCell<R, T>,
425    init: Cell<Option<F>>,
426}
427
428impl<R: RawMutex, T: fmt::Debug, F> fmt::Debug for Lazy<R, T, F> {
429    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
430        f.debug_struct("Lazy")
431            .field("cell", &self.cell)
432            .field("init", &"..")
433            .finish()
434    }
435}
436
437// We never create a `&F` from a `&Lazy<T, F>` so it is fine to not impl
438// `Sync` for `F`. We do create a `&mut Option<F>` in `force`, but this is
439// properly synchronized, so it only happens once so it also does not
440// contribute to this impl.
441unsafe impl<R, T, F: Send> Sync for Lazy<R, T, F> where OnceCell<R, T>: Sync {}
442// auto-derived `Send` impl is OK.
443
444impl<R, T, F: RefUnwindSafe> RefUnwindSafe for Lazy<R, T, F> where OnceCell<R, T>: RefUnwindSafe {}
445
446impl<R: RawMutex, T, F> Lazy<R, T, F> {
447    /// Creates a new lazy value with the given initializing
448    /// function.
449    pub const fn new(f: F) -> Self {
450        Self {
451            cell: OnceCell::new(),
452            init: Cell::new(Some(f)),
453        }
454    }
455
456    /// Consumes this `Lazy` returning the stored value.
457    ///
458    /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
459    pub fn into_value(this: Lazy<R, T, F>) -> Result<T, F> {
460        let cell = this.cell;
461        let init = this.init;
462        cell.into_inner().ok_or_else(|| {
463            init.take()
464                .unwrap_or_else(|| panic!("Lazy instance has previously been poisoned"))
465        })
466    }
467}
468
469impl<R: RawMutex, T, F: FnOnce() -> T> Lazy<R, T, F> {
470    /// Forces the evaluation of this lazy value and
471    /// returns a reference to the result. This is equivalent
472    /// to the `Deref` impl, but is explicit.
473    ///
474    /// # Example
475    /// ```
476    /// # use parking_lot::RawMutex;
477    /// use generic_once_cell::Lazy;
478    ///
479    /// let lazy = Lazy::<RawMutex, _>::new(|| 92);
480    ///
481    /// assert_eq!(Lazy::force(&lazy), &92);
482    /// assert_eq!(&*lazy, &92);
483    /// ```
484    pub fn force(this: &Self) -> &T {
485        this.cell.get_or_init(|| match this.init.take() {
486            Some(f) => f(),
487            None => panic!("Lazy instance has previously been poisoned"),
488        })
489    }
490
491    /// Forces the evaluation of this lazy value and
492    /// returns a mutable reference to the result. This is equivalent
493    /// to the `Deref` impl, but is explicit.
494    ///
495    /// # Example
496    /// ```
497    /// # use parking_lot::RawMutex;
498    /// use generic_once_cell::Lazy;
499    ///
500    /// let mut lazy = Lazy::<RawMutex, _>::new(|| 92);
501    ///
502    /// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92);
503    /// ```
504    pub fn force_mut(this: &mut Self) -> &mut T {
505        Self::force(this);
506        Self::get_mut(this).unwrap_or_else(|| unreachable!())
507    }
508
509    /// Gets the reference to the result of this lazy value if
510    /// it was initialized, otherwise returns `None`.
511    ///
512    /// # Example
513    /// ```
514    /// # use parking_lot::RawMutex;
515    /// use generic_once_cell::Lazy;
516    ///
517    /// let lazy = Lazy::<RawMutex, _>::new(|| 92);
518    ///
519    /// assert_eq!(Lazy::get(&lazy), None);
520    /// assert_eq!(&*lazy, &92);
521    /// assert_eq!(Lazy::get(&lazy), Some(&92));
522    /// ```
523    pub fn get(this: &Self) -> Option<&T> {
524        this.cell.get()
525    }
526
527    /// Gets the reference to the result of this lazy value if
528    /// it was initialized, otherwise returns `None`.
529    ///
530    /// # Example
531    /// ```
532    /// # use parking_lot::RawMutex;
533    /// use generic_once_cell::Lazy;
534    ///
535    /// let mut lazy = Lazy::<RawMutex, _>::new(|| 92);
536    ///
537    /// assert_eq!(Lazy::get_mut(&mut lazy), None);
538    /// assert_eq!(&*lazy, &92);
539    /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92));
540    /// ```
541    pub fn get_mut(this: &mut Self) -> Option<&mut T> {
542        this.cell.get_mut()
543    }
544}
545
546impl<R: RawMutex, T, F: FnOnce() -> T> Deref for Lazy<R, T, F> {
547    type Target = T;
548    fn deref(&self) -> &T {
549        Self::force(self)
550    }
551}
552
553impl<R: RawMutex, T, F: FnOnce() -> T> DerefMut for Lazy<R, T, F> {
554    fn deref_mut(&mut self) -> &mut T {
555        Self::force(self);
556        self.cell.get_mut().unwrap_or_else(|| unreachable!())
557    }
558}
559
560impl<R: RawMutex, T: Default> Default for Lazy<R, T> {
561    /// Creates a new lazy value using `Default` as the initializing function.
562    fn default() -> Self {
563        Self::new(T::default)
564    }
565}
566
567/// ```compile_fail
568/// struct S(*mut ());
569/// unsafe impl Sync for S {}
570///
571/// fn share<T: Sync>(_: &T) {}
572/// share(&generic_once_cell::OnceCell::<parking_lot::RawMutex, S>::new());
573/// ```
574///
575/// ```compile_fail
576/// struct S(*mut ());
577/// unsafe impl Sync for S {}
578///
579/// fn share<T: Sync>(_: &T) {}
580/// share(&generic_once_cell::Lazy::<parking_lot::RawMutex, S>::new(|| unimplemented!()));
581/// ```
582///
583/// ```compile_fail
584/// struct M(core::marker::PhantomData<*mut ()>);
585///
586/// unsafe impl lock_api::RawMutex for M {
587///     const INIT: Self = M(core::marker::PhantomData);
588///     type GuardMarker = lock_api::GuardNoSend;
589///     fn lock(&self) {}
590///     fn try_lock(&self) -> bool { unimplemented!() }
591///     unsafe fn unlock(&self) {}
592/// }
593///
594/// fn share<T: Sync>(_: &T) {}
595/// share(&generic_once_cell::OnceCell::<M, ()>::new());
596/// ```
597///
598/// ```compile_fail
599/// struct M(core::marker::PhantomData<*mut ()>);
600///
601/// unsafe impl lock_api::RawMutex for M {
602///     const INIT: Self = M(core::marker::PhantomData);
603///     type GuardMarker = lock_api::GuardNoSend;
604///     fn lock(&self) {}
605///     fn try_lock(&self) -> bool { unimplemented!() }
606///     unsafe fn unlock(&self) {}
607/// }
608///
609/// fn share<T: Sync>(_: &T) {}
610/// share(&generic_once_cell::Lazy::<M, ()>::new(|| unimplemented!()));
611/// ```
612fn _dummy() {}