From 29c9daf53e3820c93e2fd78280b2fc0406879a96 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Fri, 25 Aug 2023 08:44:45 +0200 Subject: [PATCH] Replace dependency on lazy-static with OnceLock --- Cargo.toml | 1 - src/lib.rs | 63 +++++++++--------------------------------------------- 2 files changed, 10 insertions(+), 54 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e63ccbe..9eb04a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -lazy_static = "1" lock_api = { version = "0.4", optional = true } parking_lot = { version = "0.12", optional = true } diff --git a/src/lib.rs b/src/lib.rs index 4b54b4f..245191c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,20 +47,17 @@ //! [paper]: https://whileydave.com/publications/pk07_jea/ #![cfg_attr(docsrs, feature(doc_cfg))] use std::cell::RefCell; -use std::cell::UnsafeCell; use std::fmt; use std::marker::PhantomData; -use std::mem::MaybeUninit; use std::ops::Deref; use std::ops::DerefMut; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use std::sync::Mutex; use std::sync::MutexGuard; -use std::sync::Once; +use std::sync::OnceLock; use std::sync::PoisonError; -use lazy_static::lazy_static; #[cfg(feature = "lockapi")] #[cfg_attr(docsrs, doc(cfg(feature = "lockapi")))] pub use lock_api; @@ -79,11 +76,6 @@ pub mod lockapi; pub mod parkinglot; pub mod stdsync; -/// Counter for Mutex IDs. Atomic avoids the need for locking. -/// -/// Should be part of the `MutexID` impl but static items are not yet a thing. -static ID_SEQUENCE: AtomicUsize = AtomicUsize::new(0); - thread_local! { /// Stack to track which locks are held /// @@ -92,10 +84,6 @@ thread_local! { static HELD_LOCKS: RefCell> = RefCell::new(Vec::new()); } -lazy_static! { - static ref DEPENDENCY_GRAPH: Mutex> = Default::default(); -} - /// Dedicated ID type for Mutexes /// /// # Unstable @@ -114,6 +102,9 @@ impl MutexId { /// This function may panic when there are no more mutex IDs available. The number of mutex ids /// is `usize::MAX - 1` which should be plenty for most practical applications. pub fn new() -> Self { + // Counter for Mutex IDs. Atomic avoids the need for locking. + static ID_SEQUENCE: AtomicUsize = AtomicUsize::new(0); + ID_SEQUENCE .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |id| id.checked_add(1)) .map(Self) @@ -207,17 +198,13 @@ impl Drop for MutexId { /// /// This type can be largely replaced once std::lazy gets stabilized. struct LazyMutexId { - inner: UnsafeCell>, - setter: Once, - _marker: PhantomData, + inner: OnceLock, } impl LazyMutexId { pub const fn new() -> Self { Self { - inner: UnsafeCell::new(MaybeUninit::uninit()), - setter: Once::new(), - _marker: PhantomData, + inner: OnceLock::new(), } } } @@ -234,44 +221,11 @@ impl Default for LazyMutexId { } } -/// Safety: the UnsafeCell is guaranteed to only be accessed mutably from a `Once`. -unsafe impl Sync for LazyMutexId {} - impl Deref for LazyMutexId { type Target = MutexId; fn deref(&self) -> &Self::Target { - self.setter.call_once(|| { - // Safety: this function is only called once, so only one mutable reference should exist - // at a time. - unsafe { - *self.inner.get() = MaybeUninit::new(MutexId::new()); - } - }); - - // Safety: after the above Once runs, there are no longer any mutable references, so we can - // hand this out safely. - // - // Explanation of this monstrosity: - // - // - Get a pointer to the data from the UnsafeCell - // - Dereference that to get a reference to the underlying MaybeUninit - // - Use as_ptr on MaybeUninit to get a pointer to the initialized MutexID - // - Dereference the pointer to turn in into a reference as intended. - // - // This should get slightly nicer once `maybe_uninit_extra` is stabilized. - unsafe { &*((*self.inner.get()).as_ptr()) } - } -} - -impl Drop for LazyMutexId { - fn drop(&mut self) { - if self.setter.is_completed() { - // We have a valid mutex ID and need to drop it - - // Safety: we know that this pointer is valid because the initializer has successfully run. - unsafe { (*self.inner.get()).assume_init_drop() }; - } + self.inner.get_or_init(MutexId::new) } } @@ -307,7 +261,10 @@ impl<'a> Drop for BorrowedMutex<'a> { /// Get a reference to the current dependency graph fn get_dependency_graph() -> impl DerefMut> { + static DEPENDENCY_GRAPH: OnceLock>> = OnceLock::new(); + DEPENDENCY_GRAPH + .get_or_init(Default::default) .lock() .unwrap_or_else(PoisonError::into_inner) }