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() {}