summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2024-03-10 20:42:37 -0400
committerMica White <botahamec@outlook.com>2024-03-10 20:42:37 -0400
commit815c0adedd6207eb406c67ea09c2634f304f8adf (patch)
treeab3f8291f2315c6c46ea472260023c14a2880261 /src
parentfe67aa262f1b04fb6c38683d9221c3a2fafcc35a (diff)
More reorganization
Diffstat (limited to 'src')
-rw-r--r--src/key.rs56
-rw-r--r--src/lib.rs9
-rw-r--r--src/mutex.rs1
-rw-r--r--src/mutex/guard.rs28
-rw-r--r--src/mutex/mutex_ref.rs33
5 files changed, 53 insertions, 74 deletions
diff --git a/src/key.rs b/src/key.rs
index d951154..887ac29 100644
--- a/src/key.rs
+++ b/src/key.rs
@@ -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);
}
diff --git a/src/lib.rs b/src/lib.rs
index dbe095c..38279fa 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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() }
- }
-}