From ded44ec228b3eaceed820585882414831eb196c0 Mon Sep 17 00:00:00 2001 From: Mica White Date: Fri, 8 Mar 2024 15:47:40 -0500 Subject: Extra lifetime shenanigans --- src/guard.rs | 30 ++++++++++++++++++++---------- src/mutex.rs | 35 ++++++++++++++++++++++++----------- 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 { // 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, thread_key: Key) -> Self { Self { mutex: MutexRef(mutex), - _thread_key: thread_key, + thread_key, + _phantom: PhantomData, } } } @@ -143,7 +150,10 @@ impl Mutex { /// 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 Mutex { /// 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> { + ) -> Option> { if self.raw.try_lock() { // safety: we just locked the mutex Some(unsafe { MutexGuard::new(self, key) }) @@ -231,8 +241,11 @@ impl Mutex { /// 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 } } -- cgit v1.2.3