mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Replace bespoke LazyLock/OnceLock with spin re-exports
Presumably notably slower on platforms with std, yet only when compiled with old versions of Rust for which the option is this or no support anyways.
This commit is contained in:
@@ -27,101 +27,18 @@ pub use mutex_shim::{ShimMutex as Mutex, MutexGuard};
|
|||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
pub use spin::Once as OnceLock;
|
pub use spin::Once as OnceLock;
|
||||||
|
#[rustversion::before(1.70)]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
mod std_oncelock {
|
pub use spin::Once as OnceLock;
|
||||||
#[rustversion::before(1.70)]
|
#[rustversion::since(1.70)]
|
||||||
mod before_1_70_oncelock {
|
|
||||||
use core::cell::Cell;
|
|
||||||
use std::sync::RwLock;
|
|
||||||
|
|
||||||
/// Shim for `std::sync::OnceLock`.
|
|
||||||
pub struct OnceLock<T> {
|
|
||||||
value: Cell<*mut T>,
|
|
||||||
init: RwLock<bool>,
|
|
||||||
}
|
|
||||||
// We use the `RwLock` (which is `Sync`) to control access to the `!Sync` `RefCell`
|
|
||||||
unsafe impl<T: Sync> Sync for OnceLock<T> {}
|
|
||||||
|
|
||||||
impl<T> OnceLock<T> {
|
|
||||||
/// Shim for `std::sync::OnceLock::new`.
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self { value: Cell::new(core::ptr::null_mut()), init: RwLock::new(false) }
|
|
||||||
}
|
|
||||||
/// Shim for `std::sync::OnceLock::get_or_init`.
|
|
||||||
pub fn get_or_init<F>(&self, f: F) -> &T
|
|
||||||
where
|
|
||||||
F: FnOnce() -> T,
|
|
||||||
{
|
|
||||||
let initialized = *self.init.read().unwrap();
|
|
||||||
if !initialized {
|
|
||||||
// Obtain an exclusive reference
|
|
||||||
let mut initialized = self.init.write().unwrap();
|
|
||||||
// If this still isn't initialized (by someone who first obtained an exlusive reference)
|
|
||||||
if !*initialized {
|
|
||||||
// Set the value and mark it initialized
|
|
||||||
self.value.set(Box::into_raw(Box::new(f())));
|
|
||||||
*initialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// SAFETY: We always initialize the value before this and it's only written to once
|
|
||||||
unsafe { &*self.value.get() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: `OnceLock` doesn't implement `Clone` so this doesn't risk dropping the `Box`
|
|
||||||
// multiple times
|
|
||||||
impl<T> Drop for OnceLock<T> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if *self.init.read().unwrap() {
|
|
||||||
unsafe { drop(Box::from_raw(self.value.get())) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[rustversion::before(1.70)]
|
|
||||||
pub use before_1_70_oncelock::OnceLock;
|
|
||||||
#[rustversion::since(1.70)]
|
|
||||||
pub use std::sync::OnceLock;
|
|
||||||
}
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std_oncelock::OnceLock;
|
pub use std::sync::OnceLock;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
pub use spin::Lazy as LazyLock;
|
pub use spin::Lazy as LazyLock;
|
||||||
|
#[rustversion::before(1.80)]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
mod std_lazylock {
|
pub use spin::Lazy as LazyLock;
|
||||||
#[rustversion::before(1.80)]
|
#[rustversion::since(1.80)]
|
||||||
mod before_1_80_lazylock {
|
|
||||||
use core::ops::Deref;
|
|
||||||
use crate::sync::{Mutex, OnceLock};
|
|
||||||
|
|
||||||
/// Shim for `std::sync::LazyLock`.
|
|
||||||
pub struct LazyLock<T, F = fn() -> T> {
|
|
||||||
f: Mutex<Option<F>>,
|
|
||||||
once: OnceLock<T>,
|
|
||||||
}
|
|
||||||
impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
|
||||||
/// Shim for `std::sync::LazyLock::new`.
|
|
||||||
pub const fn new(f: F) -> Self {
|
|
||||||
Self { f: Mutex::new(Some(f)), once: OnceLock::new() }
|
|
||||||
}
|
|
||||||
/// Shim for `std::sync::LazyLock::get`.
|
|
||||||
pub fn get(&self) -> &T {
|
|
||||||
// Since this initializer will only be called once, the value in the Mutex will be `Some`
|
|
||||||
self.once.get_or_init(|| (self.f.lock().take().unwrap())())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
|
|
||||||
type Target = T;
|
|
||||||
fn deref(&self) -> &T {
|
|
||||||
self.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[rustversion::before(1.80)]
|
|
||||||
pub use before_1_80_lazylock::LazyLock;
|
|
||||||
#[rustversion::since(1.80)]
|
|
||||||
pub use std::sync::LazyLock;
|
|
||||||
}
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std_lazylock::LazyLock;
|
pub use std::sync::LazyLock;
|
||||||
|
|||||||
Reference in New Issue
Block a user