diff options
| author | Mica White <botahamec@outlook.com> | 2025-03-12 22:19:38 -0400 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2025-03-12 22:19:38 -0400 |
| commit | f347b3e7ca771f11a21d2f6e54c0d97796174d37 (patch) | |
| tree | 6776aa84a0fb91f5619f9669f083e0316f0526b9 /src/rwlock | |
| parent | 58abf5872023aca7ee6459fa3b2e067d57923ba5 (diff) | |
Add unwind handling for scoped locks
Diffstat (limited to 'src/rwlock')
| -rw-r--r-- | src/rwlock/read_lock.rs | 2 | ||||
| -rw-r--r-- | src/rwlock/rwlock.rs | 89 | ||||
| -rw-r--r-- | src/rwlock/write_lock.rs | 2 |
3 files changed, 82 insertions, 11 deletions
diff --git a/src/rwlock/read_lock.rs b/src/rwlock/read_lock.rs index dd9e42f..f13f2b9 100644 --- a/src/rwlock/read_lock.rs +++ b/src/rwlock/read_lock.rs @@ -49,7 +49,7 @@ unsafe impl<T, R: RawRwLock> Lockable for ReadLock<'_, T, R> { Self: 'a; fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) { - ptrs.push(self); + ptrs.push(self.0); } unsafe fn guard(&self) -> Self::Guard<'_> { diff --git a/src/rwlock/rwlock.rs b/src/rwlock/rwlock.rs index 5f407d1..f1cdca5 100644 --- a/src/rwlock/rwlock.rs +++ b/src/rwlock/rwlock.rs @@ -5,7 +5,6 @@ use std::panic::AssertUnwindSafe; use lock_api::RawRwLock; -use crate::collection::utils; use crate::handle_unwind::handle_unwind; use crate::lockable::{ Lockable, LockableGetMut, LockableIntoInner, OwnedLockable, RawLock, Sharable, @@ -118,9 +117,9 @@ unsafe impl<T, R: RawRwLock> Sharable for RwLock<T, R> { } } -unsafe impl<T: Send, R: RawRwLock> OwnedLockable for RwLock<T, R> {} +unsafe impl<T, R: RawRwLock> OwnedLockable for RwLock<T, R> {} -impl<T: Send, R: RawRwLock> LockableIntoInner for RwLock<T, R> { +impl<T, R: RawRwLock> LockableIntoInner for RwLock<T, R> { type Inner = T; fn into_inner(self) -> Self::Inner { @@ -128,7 +127,7 @@ impl<T: Send, R: RawRwLock> LockableIntoInner for RwLock<T, R> { } } -impl<T: Send, R: RawRwLock> LockableGetMut for RwLock<T, R> { +impl<T, R: RawRwLock> LockableGetMut for RwLock<T, R> { type Inner<'a> = &'a mut T where @@ -248,9 +247,26 @@ impl<T: ?Sized, R> RwLock<T, R> { } } -impl<T, R: RawRwLock> RwLock<T, R> { +impl<T: ?Sized, R: RawRwLock> RwLock<T, R> { pub fn scoped_read<'a, Ret>(&'a self, key: impl Keyable, f: impl Fn(&'a T) -> Ret) -> Ret { - utils::scoped_read(self, key, f) + unsafe { + // safety: we have the key + self.raw_read(); + + // safety: the data has been locked + let r = handle_unwind( + || f(self.data.get().as_ref().unwrap_unchecked()), + || self.raw_unlock_read(), + ); + + // ensures the key is held long enough + drop(key); + + // safety: the mutex is still locked + self.raw_unlock_read(); + + r + } } pub fn scoped_try_read<'a, Key: Keyable, Ret>( @@ -258,11 +274,47 @@ impl<T, R: RawRwLock> RwLock<T, R> { key: Key, f: impl Fn(&'a T) -> Ret, ) -> Result<Ret, Key> { - utils::scoped_try_read(self, key, f) + unsafe { + // safety: we have the key + if !self.raw_try_read() { + return Err(key); + } + + // safety: the data has been locked + let r = handle_unwind( + || f(self.data.get().as_ref().unwrap_unchecked()), + || self.raw_unlock_read(), + ); + + // ensures the key is held long enough + drop(key); + + // safety: the mutex is still locked + self.raw_unlock_read(); + + Ok(r) + } } pub fn scoped_write<'a, Ret>(&'a self, key: impl Keyable, f: impl Fn(&'a mut T) -> Ret) -> Ret { - utils::scoped_write(self, key, f) + unsafe { + // safety: we have the key + self.raw_write(); + + // safety: the data has been locked + let r = handle_unwind( + || f(self.data.get().as_mut().unwrap_unchecked()), + || self.raw_unlock_write(), + ); + + // ensures the key is held long enough + drop(key); + + // safety: the mutex is still locked + self.raw_unlock_write(); + + r + } } pub fn scoped_try_write<'a, Key: Keyable, Ret>( @@ -270,7 +322,26 @@ impl<T, R: RawRwLock> RwLock<T, R> { key: Key, f: impl Fn(&'a mut T) -> Ret, ) -> Result<Ret, Key> { - utils::scoped_try_write(self, key, f) + unsafe { + // safety: we have the key + if !self.raw_try_write() { + return Err(key); + } + + // safety: the data has been locked + let r = handle_unwind( + || f(self.data.get().as_mut().unwrap_unchecked()), + || self.raw_unlock_write(), + ); + + // ensures the key is held long enough + drop(key); + + // safety: the mutex is still locked + self.raw_unlock_write(); + + Ok(r) + } } /// Locks this `RwLock` with shared read access, blocking the current diff --git a/src/rwlock/write_lock.rs b/src/rwlock/write_lock.rs index 5ae4dda..6469a67 100644 --- a/src/rwlock/write_lock.rs +++ b/src/rwlock/write_lock.rs @@ -49,7 +49,7 @@ unsafe impl<T, R: RawRwLock> Lockable for WriteLock<'_, T, R> { Self: 'a; fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) { - ptrs.push(self) + ptrs.push(self.0); } unsafe fn guard(&self) -> Self::Guard<'_> { |
