Use spin's Once for OnceLock

This commit is contained in:
Luke Parker 2023-07-26 02:59:24 -04:00
parent 821f5d8de4
commit afb385fba4
No known key found for this signature in database
2 changed files with 7 additions and 27 deletions

View file

@ -13,7 +13,7 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"] rustdoc-args = ["--cfg", "docsrs"]
[dependencies] [dependencies]
spin = "0.9" spin = { version = "0.9", features = ["mutex", "once"] }
hashbrown = "0.14" hashbrown = "0.14"
[features] [features]

View file

@ -29,42 +29,22 @@ pub use mutex_shim::{ShimMutex as Mutex, MutexGuard};
pub use std::sync::OnceLock; pub use std::sync::OnceLock;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
mod oncelock_shim { mod oncelock_shim {
use super::Mutex; use spin::Once;
pub struct OnceLock<T>(Mutex<bool>, Option<T>); pub struct OnceLock<T>(Once<T>);
impl<T> OnceLock<T> { impl<T> OnceLock<T> {
pub const fn new() -> OnceLock<T> { pub const fn new() -> OnceLock<T> {
OnceLock(Mutex::new(false), None) OnceLock(Once::new())
} }
// These return a distinct Option in case of None so another caller using get_or_init doesn't
// transform it from None to Some
pub fn get(&self) -> Option<&T> { pub fn get(&self) -> Option<&T> {
if !*self.0.lock() { self.0.poll()
None
} else {
self.1.as_ref()
}
} }
pub fn get_mut(&mut self) -> Option<&mut T> { pub fn get_mut(&mut self) -> Option<&mut T> {
if !*self.0.lock() { self.0.get_mut()
None
} else {
self.1.as_mut()
}
} }
pub fn get_or_init<F: FnOnce() -> T>(&self, f: F) -> &T { pub fn get_or_init<F: FnOnce() -> T>(&self, f: F) -> &T {
let mut lock = self.0.lock(); self.0.call_once(f)
if !*lock {
unsafe {
core::ptr::addr_of!(self.1).cast_mut().write_unaligned(Some(f()));
}
}
*lock = true;
drop(lock);
self.get().unwrap()
} }
} }
} }