diff options
| author | Mica White <botahamec@outlook.com> | 2024-03-10 20:42:37 -0400 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2024-03-10 20:42:37 -0400 |
| commit | 815c0adedd6207eb406c67ea09c2634f304f8adf (patch) | |
| tree | ab3f8291f2315c6c46ea472260023c14a2880261 /src | |
| parent | fe67aa262f1b04fb6c38683d9221c3a2fafcc35a (diff) | |
More reorganization
Diffstat (limited to 'src')
| -rw-r--r-- | src/key.rs | 56 | ||||
| -rw-r--r-- | src/lib.rs | 9 | ||||
| -rw-r--r-- | src/mutex.rs | 1 | ||||
| -rw-r--r-- | src/mutex/guard.rs | 28 | ||||
| -rw-r--r-- | src/mutex/mutex_ref.rs | 33 |
5 files changed, 53 insertions, 74 deletions
@@ -5,11 +5,11 @@ use std::sync::atomic::{AtomicBool, Ordering}; use once_cell::sync::Lazy; use thread_local::ThreadLocal; -use self::sealed::Sealed; -use super::ThreadKey; +use sealed::Sealed; mod sealed { - use crate::ThreadKey; + use super::ThreadKey; + pub trait Sealed {} impl Sealed for ThreadKey {} impl Sealed for &mut ThreadKey {} @@ -17,10 +17,12 @@ mod sealed { static KEY: Lazy<ThreadLocal<AtomicLock>> = Lazy::new(ThreadLocal::new); -/// A key that can be obtained and dropped -pub struct Key<'a> { +/// The key for the current thread. +/// +/// Only one of these exist per thread. To get the current thread's key, call +/// [`ThreadKey::lock`]. If the `ThreadKey` is dropped, it can be reobtained. +pub struct ThreadKey { phantom: PhantomData<*const ()>, // implement !Send and !Sync - lock: &'a AtomicLock, } /// Allows the type to be used as a key for a lock @@ -40,9 +42,9 @@ impl Debug for ThreadKey { } } -impl<'a> Drop for Key<'a> { +impl Drop for ThreadKey { fn drop(&mut self) { - unsafe { self.lock.force_unlock() } + unsafe { KEY.get().unwrap().force_unlock() } } } @@ -50,19 +52,22 @@ impl ThreadKey { /// Get the current thread's `ThreadKey`, if it's not already taken. /// /// The first time this is called, it will successfully return a - /// `ThreadKey`. However, future calls to this function will return - /// [`None`], unless the key is dropped or unlocked first. + /// `ThreadKey`. However, future calls to this function on the same thread + /// will return [`None`], unless the key is dropped or unlocked first. #[must_use] pub fn lock() -> Option<Self> { - KEY.get_or_default().try_lock() + // safety: we just acquired the lock + KEY.get_or_default().try_lock().then_some(Self { + phantom: PhantomData, + }) } /// Unlocks the `ThreadKey`. /// /// After this method is called, a call to [`ThreadKey::lock`] will return /// this `ThreadKey`. - pub fn unlock(key: Self) { - drop(key); + pub fn unlock(self) { + drop(self); } } @@ -73,29 +78,14 @@ struct AtomicLock { } impl AtomicLock { - /// Attempt to lock the `AtomicLock`. - /// - /// If the lock is already locked, then this'll return false. If it is - /// unlocked, it'll return true. If the lock is currently unlocked, then it - /// will be locked after this function is called. - /// - /// This is not a fair lock. It is not recommended to call this function - /// repeatedly in a loop. + /// Attempt to lock the `AtomicLock`. This is not a fair lock. #[must_use] - pub fn try_lock(&self) -> Option<Key> { - // safety: we just acquired the lock - (!self.is_locked.swap(true, Ordering::Acquire)).then_some(Key { - phantom: PhantomData, - lock: self, - }) + pub fn try_lock(&'static self) -> bool { + !self.is_locked.swap(true, Ordering::Acquire) } - /// Forcibly unlocks the `AtomicLock`. - /// - /// # Safety - /// - /// This should only be called if the key to the lock has been "lost". That - /// means the program no longer has a reference to the key. + /// Forcibly unlocks the `AtomicLock`. This should only be called if the + /// key to the lock has been "lost". pub unsafe fn force_unlock(&self) { self.is_locked.store(false, Ordering::Release); } @@ -6,24 +6,19 @@ #![allow(clippy::module_inception)] mod collection; +mod key; mod lockable; -pub mod key; pub mod mutex; pub mod rwlock; pub use collection::LockCollection; +pub use key::{Keyable, ThreadKey}; pub use lockable::{Lockable, OwnedLockable}; #[cfg(feature = "spin")] pub use mutex::SpinLock; -/// The key for the current thread. -/// -/// Only one of these exist per thread. To get the current thread's key, call -/// [`ThreadKey::lock`]. If the `ThreadKey` is dropped, it can be reobtained. -pub type ThreadKey = key::Key<'static>; - /// A mutual exclusion primitive useful for protecting shared data, which cannot deadlock. /// /// By default, this uses `parking_lot` as a backend. diff --git a/src/mutex.rs b/src/mutex.rs index db0147f..0da1460 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -7,7 +7,6 @@ use crate::key::Keyable; mod guard; mod mutex; -mod mutex_ref; /// A spinning mutex #[cfg(feature = "spin")] diff --git a/src/mutex/guard.rs b/src/mutex/guard.rs index b4005e1..5d249ee 100644 --- a/src/mutex/guard.rs +++ b/src/mutex/guard.rs @@ -7,6 +7,34 @@ use crate::key::Keyable; use super::{Mutex, MutexGuard, MutexRef}; +impl<'a, T: ?Sized + 'a, R: RawMutex> Drop for MutexRef<'a, T, R> { + fn drop(&mut self) { + // safety: this guard is being destroyed, so the data cannot be + // accessed without locking again + unsafe { self.0.force_unlock() } + } +} + +impl<'a, T: ?Sized + 'a, R: RawMutex> Deref for MutexRef<'a, T, R> { + type Target = T; + + fn deref(&self) -> &Self::Target { + // safety: this is the only type that can use `value`, and there's + // a reference to this type, so there cannot be any mutable + // references to this value. + unsafe { &*self.0.value.get() } + } +} + +impl<'a, T: ?Sized + 'a, R: RawMutex> DerefMut for MutexRef<'a, T, R> { + fn deref_mut(&mut self) -> &mut Self::Target { + // safety: this is the only type that can use `value`, and we have a + // mutable reference to this type, so there cannot be any other + // references to this value. + unsafe { &mut *self.0.value.get() } + } +} + impl<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> Deref for MutexGuard<'a, 'key, T, Key, R> { diff --git a/src/mutex/mutex_ref.rs b/src/mutex/mutex_ref.rs deleted file mode 100644 index 5222719..0000000 --- a/src/mutex/mutex_ref.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::ops::{Deref, DerefMut}; - -use lock_api::RawMutex; - -use super::MutexRef; - -impl<'a, T: ?Sized + 'a, R: RawMutex> Drop for MutexRef<'a, T, R> { - fn drop(&mut self) { - // safety: this guard is being destroyed, so the data cannot be - // accessed without locking again - unsafe { self.0.force_unlock() } - } -} - -impl<'a, T: ?Sized + 'a, R: RawMutex> Deref for MutexRef<'a, T, R> { - type Target = T; - - fn deref(&self) -> &Self::Target { - // safety: this is the only type that can use `value`, and there's - // a reference to this type, so there cannot be any mutable - // references to this value. - unsafe { &*self.0.value.get() } - } -} - -impl<'a, T: ?Sized + 'a, R: RawMutex> DerefMut for MutexRef<'a, T, R> { - fn deref_mut(&mut self) -> &mut Self::Target { - // safety: this is the only type that can use `value`, and we have a - // mutable reference to this type, so there cannot be any other - // references to this value. - unsafe { &mut *self.0.value.get() } - } -} |
