//!
//! This crate's minimum supported `rustc` version is `1.56.0`.
//!
-//! If only the `std` feature is enabled, MSRV will be updated conservatively.
+//! If only the `std` feature is enabled, MSRV will be updated conservatively, supporting at least latest 8 versions of the compiler.
//! When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable.
//! In both cases, increasing MSRV is *not* considered a semver-breaking change.
//!
#[cfg(feature = "alloc")]
extern crate alloc;
-#[cfg(feature = "std")]
-#[cfg(feature = "parking_lot")]
+#[cfg(all(feature = "critical-section", not(feature = "std")))]
+#[path = "imp_cs.rs"]
+mod imp;
+
+#[cfg(all(feature = "std", feature = "parking_lot"))]
#[path = "imp_pl.rs"]
mod imp;
-#[cfg(feature = "std")]
-#[cfg(not(feature = "parking_lot"))]
+#[cfg(all(feature = "std", not(feature = "parking_lot")))]
#[path = "imp_std.rs"]
mod imp;
pub mod unsync {
use core::{
cell::{Cell, UnsafeCell},
- fmt, hint, mem,
+ fmt, mem,
ops::{Deref, DerefMut},
panic::{RefUnwindSafe, UnwindSafe},
};
+ use super::unwrap_unchecked;
+
/// A cell which can be written to only once. It is not thread safe.
///
/// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&`
/// Gets a reference to the underlying value.
///
/// Returns `None` if the cell is empty.
+ #[inline]
pub fn get(&self) -> Option<&T> {
// Safe due to `inner`'s invariant
unsafe { &*self.inner.get() }.as_ref()
/// *cell.get_mut().unwrap() = 93;
/// assert_eq!(cell.get(), Some(&93));
/// ```
+ #[inline]
pub fn get_mut(&mut self) -> Option<&mut T> {
// Safe because we have unique access
unsafe { &mut *self.inner.get() }.as_mut()
if let Some(old) = self.get() {
return Err((old, value));
}
+
let slot = unsafe { &mut *self.inner.get() };
// This is the only place where we set the slot, no races
// due to reentrancy/concurrency are possible, and we've
// checked that slot is currently `None`, so this write
// maintains the `inner`'s invariant.
*slot = Some(value);
- Ok(match &*slot {
- Some(value) => value,
- None => unsafe { hint::unreachable_unchecked() },
- })
+ Ok(unsafe { unwrap_unchecked(slot.as_ref()) })
}
/// Gets the contents of the cell, initializing it with `f`
// `assert`, while keeping `set/get` would be sound, but it seems
// better to panic, rather than to silently use an old value.
assert!(self.set(val).is_ok(), "reentrant init");
- Ok(self.get().unwrap())
+ Ok(unsafe { unwrap_unchecked(self.get()) })
}
/// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
}
/// Thread-safe, blocking version of `OnceCell`.
-#[cfg(feature = "std")]
+#[cfg(any(feature = "std", feature = "critical-section"))]
pub mod sync {
- use std::{
+ use core::{
cell::Cell,
fmt, mem,
ops::{Deref, DerefMut},
panic::RefUnwindSafe,
};
- use crate::{imp::OnceCell as Imp, take_unchecked};
+ use super::{imp::OnceCell as Imp, unwrap_unchecked};
/// A thread-safe cell which can be written to only once.
///
/// // Will return 92, but might block until the other thread does `.set`.
/// let value: &u32 = cell.wait();
/// assert_eq!(*value, 92);
- /// t.join().unwrap();;
+ /// t.join().unwrap();
/// ```
+ #[cfg(feature = "std")]
pub fn wait(&self) -> &T {
if !self.0.is_initialized() {
self.0.wait()
/// cell.set(92).unwrap();
/// cell = OnceCell::new();
/// ```
+ #[inline]
pub fn get_mut(&mut self) -> Option<&mut T> {
self.0.get_mut()
}
///
/// Caller must ensure that the cell is in initialized state, and that
/// the contents are acquired by (synchronized to) this thread.
+ #[inline]
pub unsafe fn get_unchecked(&self) -> &T {
self.0.get_unchecked()
}
/// ```
pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
let mut value = Some(value);
- let res = self.get_or_init(|| unsafe { take_unchecked(&mut value) });
+ let res = self.get_or_init(|| unsafe { unwrap_unchecked(value.take()) });
match value {
None => Ok(res),
Some(value) => Err((res, value)),
if let Some(value) = self.get() {
return Ok(value);
}
+
self.0.initialize(f)?;
// Safe b/c value is initialized.
/// cell.set("hello".to_string()).unwrap();
/// assert_eq!(cell.into_inner(), Some("hello".to_string()));
/// ```
+ #[inline]
pub fn into_inner(self) -> Option<T> {
self.0.into_inner()
}
#[cfg(feature = "race")]
pub mod race;
-#[cfg(feature = "std")]
-unsafe fn take_unchecked<T>(val: &mut Option<T>) -> T {
- match val.take() {
- Some(it) => it,
+// Remove once MSRV is at least 1.58.
+#[inline]
+unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T {
+ match val {
+ Some(value) => value,
None => {
debug_assert!(false);
- std::hint::unreachable_unchecked()
+ core::hint::unreachable_unchecked()
}
}
}