summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/guard.rs30
-rw-r--r--src/mutex.rs35
2 files changed, 44 insertions, 21 deletions
diff --git a/src/guard.rs b/src/guard.rs
index 30e7d4a..12021e2 100644
--- a/src/guard.rs
+++ b/src/guard.rs
@@ -1,21 +1,26 @@
-use std::ops::{Deref, DerefMut};
+use std::{
+ marker::PhantomData,
+ ops::{Deref, DerefMut},
+};
use crate::{key::Keyable, lockable::Lockable};
/// A guard for a generic [`Lockable`] type.
-pub struct LockGuard<'a, L: Lockable<'a>, Key: Keyable> {
+pub struct LockGuard<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable + 'key> {
guard: L::Output,
- _key: Key,
+ key: Key,
+ _phantom: PhantomData<&'key ()>,
}
-impl<'a, L: Lockable<'a>, Key: Keyable> LockGuard<'a, L, Key> {
+impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> LockGuard<'a, 'key, L, Key> {
/// Locks the lockable type and returns a guard that can be used to access
/// the underlying data.
pub fn lock(lock: &'a L, key: Key) -> Self {
Self {
// safety: we have the thread's key
guard: unsafe { lock.lock() },
- _key: key,
+ key,
+ _phantom: PhantomData,
}
}
@@ -24,18 +29,23 @@ impl<'a, L: Lockable<'a>, Key: Keyable> LockGuard<'a, L, Key> {
/// is given back as an error.
pub fn try_lock(lock: &'a L, key: Key) -> Option<Self> {
// safety: we have the thread's key
- unsafe { lock.try_lock() }.map(|guard| Self { guard, _key: key })
+ unsafe { lock.try_lock() }.map(|guard| Self {
+ guard,
+ key,
+ _phantom: PhantomData,
+ })
}
/// Unlocks the underlying lockable data type, returning the key that's
/// associated with it.
#[allow(clippy::missing_const_for_fn)]
- pub fn unlock(self) {
- L::unlock(self.guard);
+ pub fn unlock(guard: Self) -> Key {
+ L::unlock(guard.guard);
+ guard.key
}
}
-impl<'a, L: Lockable<'a>, Key: Keyable> Deref for LockGuard<'a, L, Key> {
+impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> Deref for LockGuard<'a, 'key, L, Key> {
type Target = L::Output;
fn deref(&self) -> &Self::Target {
@@ -43,7 +53,7 @@ impl<'a, L: Lockable<'a>, Key: Keyable> Deref for LockGuard<'a, L, Key> {
}
}
-impl<'a, L: Lockable<'a>, Key: Keyable> DerefMut for LockGuard<'a, L, Key> {
+impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> DerefMut for LockGuard<'a, 'key, L, Key> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.guard
}
diff --git a/src/mutex.rs b/src/mutex.rs
index f395055..9298b0c 100644
--- a/src/mutex.rs
+++ b/src/mutex.rs
@@ -1,4 +1,5 @@
use std::cell::UnsafeCell;
+use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use lock_api::RawMutex;
@@ -71,12 +72,15 @@ impl<'a, T: ?Sized + 'a, R: RawMutex> DerefMut for MutexRef<'a, T, R> {
///
/// [`lock`]: `Mutex::lock`
/// [`try_lock`]: `Mutex::try_lock`
-pub struct MutexGuard<'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> {
+pub struct MutexGuard<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable + 'key, R: RawMutex> {
mutex: MutexRef<'a, T, R>,
- _thread_key: Key,
+ thread_key: Key,
+ _phantom: PhantomData<&'key ()>,
}
-impl<'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> Deref for MutexGuard<'a, T, Key, R> {
+impl<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> Deref
+ for MutexGuard<'a, 'key, T, Key, R>
+{
type Target = T;
fn deref(&self) -> &Self::Target {
@@ -84,19 +88,22 @@ impl<'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> Deref for MutexGuard<'a, T,
}
}
-impl<'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> DerefMut for MutexGuard<'a, T, Key, R> {
+impl<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> DerefMut
+ for MutexGuard<'a, 'key, T, Key, R>
+{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.mutex
}
}
-impl<'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> MutexGuard<'a, T, Key, R> {
+impl<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> MutexGuard<'a, 'key, T, Key, R> {
/// Create a guard to the given mutex. Undefined if multiple guards to the
/// same mutex exist at once.
const unsafe fn new(mutex: &'a Mutex<T, R>, thread_key: Key) -> Self {
Self {
mutex: MutexRef(mutex),
- _thread_key: thread_key,
+ thread_key,
+ _phantom: PhantomData,
}
}
}
@@ -143,7 +150,10 @@ impl<T: ?Sized, R: RawMutex> Mutex<T, R> {
/// let key = ThreadKey::lock().unwrap();
/// assert_eq!(*mutex.lock(key), 10);
/// ```
- pub fn lock<'s, 'a: 's, Key: Keyable>(&'s self, key: Key) -> MutexGuard<'_, T, Key, R> {
+ pub fn lock<'s, 'a: 's, 'k: 'a, Key: Keyable>(
+ &'s self,
+ key: Key,
+ ) -> MutexGuard<'_, 'k, T, Key, R> {
self.raw.lock();
// safety: we just locked the mutex
@@ -187,10 +197,10 @@ impl<T: ?Sized, R: RawMutex> Mutex<T, R> {
/// let key = ThreadKey::lock().unwrap();
/// assert_eq!(*mutex.lock(key), 10);
/// ```
- pub fn try_lock<'s, 'a: 's, Key: Keyable>(
+ pub fn try_lock<'s, 'a: 's, 'k: 'a, Key: Keyable>(
&'s self,
key: Key,
- ) -> Option<MutexGuard<'_, T, Key, R>> {
+ ) -> Option<MutexGuard<'_, 'k, T, Key, R>> {
if self.raw.try_lock() {
// safety: we just locked the mutex
Some(unsafe { MutexGuard::new(self, key) })
@@ -231,8 +241,11 @@ impl<T: ?Sized, R: RawMutex> Mutex<T, R> {
/// let key = Mutex::unlock(guard);
/// ```
#[allow(clippy::missing_const_for_fn)]
- pub fn unlock(guard: MutexGuard<'_, T, impl Keyable, R>) {
- drop(guard);
+ pub fn unlock<'a, 'k: 'a, Key: Keyable + 'k>(guard: MutexGuard<'a, 'k, T, Key, R>) -> Key {
+ unsafe {
+ guard.mutex.0.force_unlock();
+ }
+ guard.thread_key
}
}