From 58abf5872023aca7ee6459fa3b2e067d57923ba5 Mon Sep 17 00:00:00 2001 From: Mica White Date: Sun, 9 Mar 2025 20:49:56 -0400 Subject: Finish testing and fixing --- src/mutex/mutex.rs | 85 +++++++++++++++++++++--------------------------------- 1 file changed, 33 insertions(+), 52 deletions(-) (limited to 'src/mutex/mutex.rs') diff --git a/src/mutex/mutex.rs b/src/mutex/mutex.rs index 1d8ce8b..f0fb680 100644 --- a/src/mutex/mutex.rs +++ b/src/mutex/mutex.rs @@ -5,6 +5,7 @@ use std::panic::AssertUnwindSafe; use lock_api::RawMutex; +use crate::collection::utils; use crate::handle_unwind::handle_unwind; use crate::lockable::{Lockable, LockableGetMut, LockableIntoInner, OwnedLockable, RawLock}; use crate::poisonable::PoisonFlag; @@ -17,7 +18,7 @@ unsafe impl RawLock for Mutex { self.poison.poison(); } - unsafe fn raw_lock(&self) { + unsafe fn raw_write(&self) { assert!(!self.poison.is_poisoned(), "The mutex has been killed"); // if the closure unwraps, then the mutex will be killed @@ -25,7 +26,7 @@ unsafe impl RawLock for Mutex { handle_unwind(|| this.raw.lock(), || self.poison()) } - unsafe fn raw_try_lock(&self) -> bool { + unsafe fn raw_try_write(&self) -> bool { if self.poison.is_poisoned() { return false; } @@ -35,7 +36,7 @@ unsafe impl RawLock for Mutex { handle_unwind(|| this.raw.try_lock(), || self.poison()) } - unsafe fn raw_unlock(&self) { + unsafe fn raw_unlock_write(&self) { // if the closure unwraps, then the mutex will be killed let this = AssertUnwindSafe(self); handle_unwind(|| this.raw.unlock(), || self.poison()) @@ -43,20 +44,26 @@ unsafe impl RawLock for Mutex { // this is the closest thing to a read we can get, but Sharable isn't // implemented for this + #[mutants::skip] + #[cfg(not(tarpaulin_include))] unsafe fn raw_read(&self) { - self.raw_lock() + self.raw_write() } + #[mutants::skip] + #[cfg(not(tarpaulin_include))] unsafe fn raw_try_read(&self) -> bool { - self.raw_try_lock() + self.raw_try_write() } + #[mutants::skip] + #[cfg(not(tarpaulin_include))] unsafe fn raw_unlock_read(&self) { - self.raw_unlock() + self.raw_unlock_write() } } -unsafe impl Lockable for Mutex { +unsafe impl Lockable for Mutex { type Guard<'g> = MutexRef<'g, T, R> where @@ -80,7 +87,7 @@ unsafe impl Lockable for Mutex { } } -impl LockableIntoInner for Mutex { +impl LockableIntoInner for Mutex { type Inner = T; fn into_inner(self) -> Self::Inner { @@ -88,7 +95,7 @@ impl LockableIntoInner for Mutex { } } -impl LockableGetMut for Mutex { +impl LockableGetMut for Mutex { type Inner<'a> = &'a mut T where @@ -99,7 +106,7 @@ impl LockableGetMut for Mutex { } } -unsafe impl OwnedLockable for Mutex {} +unsafe impl OwnedLockable for Mutex {} impl Mutex { /// Create a new unlocked `Mutex`. @@ -140,7 +147,7 @@ impl Mutex { #[mutants::skip] #[cfg(not(tarpaulin_include))] -impl Debug for Mutex { +impl Debug for Mutex { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // safety: this is just a try lock, and the value is dropped // immediately after, so there's no risk of blocking ourselves @@ -222,45 +229,21 @@ impl Mutex { } } -impl Mutex { - pub fn scoped_lock(&self, key: impl Keyable, f: impl FnOnce(&mut T) -> Ret) -> Ret { - unsafe { - // safety: we have the thread key - self.raw_lock(); - - // safety: the mutex was just locked - let r = f(self.data.get().as_mut().unwrap_unchecked()); - - // safety: we locked the mutex already - self.raw_unlock(); - - drop(key); // ensures we drop the key in the correct place - - r - } +impl Mutex { + pub fn scoped_lock<'a, Ret>( + &'a self, + key: impl Keyable, + f: impl FnOnce(&'a mut T) -> Ret, + ) -> Ret { + utils::scoped_write(self, key, f) } - pub fn scoped_try_lock( - &self, + pub fn scoped_try_lock<'a, Key: Keyable, Ret>( + &'a self, key: Key, - f: impl FnOnce(&mut T) -> Ret, + f: impl FnOnce(&'a mut T) -> Ret, ) -> Result { - unsafe { - // safety: we have the thread key - if !self.raw_try_lock() { - return Err(key); - } - - // safety: the mutex was just locked - let r = f(self.data.get().as_mut().unwrap_unchecked()); - - // safety: we locked the mutex already - self.raw_unlock(); - - drop(key); // ensures we drop the key in the correct place - - Ok(r) - } + utils::scoped_try_write(self, key, f) } /// Block the thread until this mutex can be locked, and lock it. @@ -289,7 +272,7 @@ impl Mutex { pub fn lock(&self, key: ThreadKey) -> MutexGuard<'_, T, R> { unsafe { // safety: we have the thread key - self.raw_lock(); + self.raw_write(); // safety: we just locked the mutex MutexGuard::new(self, key) @@ -332,7 +315,7 @@ impl Mutex { pub fn try_lock(&self, key: ThreadKey) -> Result, ThreadKey> { unsafe { // safety: we have the key to the mutex - if self.raw_try_lock() { + if self.raw_try_write() { // safety: we just locked the mutex Ok(MutexGuard::new(self, key)) } else { @@ -350,7 +333,7 @@ impl Mutex { /// Lock without a [`ThreadKey`]. It is undefined behavior to do this without /// owning the [`ThreadKey`]. pub(crate) unsafe fn try_lock_no_key(&self) -> Option> { - self.raw_try_lock().then_some(MutexRef(self, PhantomData)) + self.raw_try_write().then_some(MutexRef(self, PhantomData)) } /// Consumes the [`MutexGuard`], and consequently unlocks its `Mutex`. @@ -370,9 +353,7 @@ impl Mutex { /// ``` #[must_use] pub fn unlock(guard: MutexGuard<'_, T, R>) -> ThreadKey { - unsafe { - guard.mutex.0.raw_unlock(); - } + drop(guard.mutex); guard.thread_key } } -- cgit v1.2.3