diff options
| author | Botahamec <botahamec@outlook.com> | 2024-09-26 22:58:13 -0400 |
|---|---|---|
| committer | Botahamec <botahamec@outlook.com> | 2024-09-26 22:58:13 -0400 |
| commit | 2376ccee97c99d5c47c09fcf308a97aaf785a29e (patch) | |
| tree | 0aa7814c78a035929d494f60dec5daa925bed433 | |
| parent | 5f55113a6ead937fc8bc81e361abc09b3a1565f3 (diff) | |
Better into_inner and get_mut implementations
| -rw-r--r-- | src/lockable.rs | 44 | ||||
| -rw-r--r-- | src/poisonable.rs | 2 | ||||
| -rw-r--r-- | src/poisonable/poisonable.rs | 66 |
3 files changed, 104 insertions, 8 deletions
diff --git a/src/lockable.rs b/src/lockable.rs index 9f44981..6eced32 100644 --- a/src/lockable.rs +++ b/src/lockable.rs @@ -151,6 +151,18 @@ pub unsafe trait Lockable { unsafe fn read_guard(&self) -> Self::ReadGuard<'_>; } +pub trait LockableIntoInner: Lockable { + type Inner; + + fn into_inner(self) -> Self::Inner; +} + +pub trait LockableAsMut: Lockable { + type Inner; + + fn as_mut(&mut self) -> &mut Self::Inner; +} + /// A marker trait to indicate that multiple readers can access the lock at a /// time. /// @@ -258,6 +270,38 @@ unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for RwLock<T, R> { } } +impl<T: Send, R: RawMutex + Send + Sync> LockableIntoInner for Mutex<T, R> { + type Inner = T; + + fn into_inner(self) -> Self::Inner { + self.into_inner() + } +} + +impl<T: Send, R: RawMutex + Send + Sync> LockableAsMut for Mutex<T, R> { + type Inner = T; + + fn as_mut(&mut self) -> &mut Self::Inner { + self.get_mut() + } +} + +impl<T: Send, R: RawRwLock + Send + Sync> LockableIntoInner for RwLock<T, R> { + type Inner = T; + + fn into_inner(self) -> Self::Inner { + self.into_inner() + } +} + +impl<T: Send, R: RawRwLock + Send + Sync> LockableAsMut for RwLock<T, R> { + type Inner = T; + + fn as_mut(&mut self) -> &mut Self::Inner { + AsMut::as_mut(self) + } +} + unsafe impl<T: Send, R: RawRwLock + Send + Sync> Sharable for RwLock<T, R> {} unsafe impl<T: Send, R: RawMutex + Send + Sync> OwnedLockable for Mutex<T, R> {} diff --git a/src/poisonable.rs b/src/poisonable.rs index a492084..6cc234e 100644 --- a/src/poisonable.rs +++ b/src/poisonable.rs @@ -35,7 +35,7 @@ struct PoisonFlag(#[cfg(panic = "unwind")] AtomicBool); /// [`into_inner`]: `PoisonError::into_inner` /// [`clear_poison`]: `Poisonable::clear_poison` #[derive(Debug, Default)] -pub struct Poisonable<L: Lockable + RawLock> { +pub struct Poisonable<L> { inner: L, poisoned: PoisonFlag, } diff --git a/src/poisonable/poisonable.rs b/src/poisonable/poisonable.rs index ff43ff8..e1c4caa 100644 --- a/src/poisonable/poisonable.rs +++ b/src/poisonable/poisonable.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use std::panic::{RefUnwindSafe, UnwindSafe}; -use crate::lockable::{Lockable, RawLock}; +use crate::lockable::{Lockable, LockableAsMut, LockableIntoInner, RawLock}; use crate::Keyable; use super::{ @@ -282,9 +282,9 @@ impl<L: Lockable + RawLock> Poisonable<L> { /// use happylock::{Mutex, Poisonable}; /// /// let mutex = Poisonable::new(Mutex::new(0)); - /// assert_eq!(mutex.into_inner().unwrap().into_inner(), 0); + /// assert_eq!(mutex.inner_lock().unwrap().into_inner(), 0); /// ``` - pub fn into_inner(self) -> PoisonResult<L> { + pub fn inner_lock(self) -> PoisonResult<L> { if self.is_poisoned() { Err(PoisonError::new(self.inner)) } else { @@ -294,6 +294,58 @@ impl<L: Lockable + RawLock> Poisonable<L> { /// Returns a mutable reference to the underlying lock. /// + /// # Errors + /// + /// If another user of this lock panicked while holding the lock, then + /// this call will return an error instead. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, Poisonable, ThreadKey}; + /// + /// let key = ThreadKey::get().unwrap(); + /// let mut mutex = Poisonable::new(Mutex::new(0)); + /// *mutex.lock_mut().unwrap().as_mut() = 10; + /// assert_eq!(*mutex.lock(key).unwrap(), 10); + /// ``` + pub fn lock_mut(&mut self) -> PoisonResult<&mut L> { + if self.is_poisoned() { + Err(PoisonError::new(&mut self.inner)) + } else { + Ok(&mut self.inner) + } + } +} + +impl<L: LockableIntoInner + RawLock> Poisonable<L> { + /// Consumes this `Poisonable`, returning the underlying data. + /// + /// # Errors + /// + /// If another user of this lock panicked while holding the lock, then this + /// call will return an error instead. + /// + /// # Examples + /// + /// ``` + /// use happylock::{Mutex, Poisonable}; + /// + /// let mutex = Poisonable::new(Mutex::new(0)); + /// assert_eq!(mutex.into_inner().unwrap(), 0); + /// ``` + pub fn into_inner(self) -> PoisonResult<L::Inner> { + if self.is_poisoned() { + Err(PoisonError::new(self.inner.into_inner())) + } else { + Ok(self.inner.into_inner()) + } + } +} + +impl<L: LockableAsMut + RawLock> Poisonable<L> { + /// Returns a mutable reference to the underlying data. + /// /// Since this call borrows the `Poisonable` mutable, no actual locking /// needs to take place - the mutable borrow statically guarantees no locks /// exist. @@ -310,14 +362,14 @@ impl<L: Lockable + RawLock> Poisonable<L> { /// /// let key = ThreadKey::get().unwrap(); /// let mut mutex = Poisonable::new(Mutex::new(0)); - /// *mutex.get_mut().unwrap().as_mut() = 10; + /// *mutex.get_mut().unwrap() = 10; /// assert_eq!(*mutex.lock(key).unwrap(), 10); /// ``` - pub fn get_mut(&mut self) -> PoisonResult<&mut L> { + pub fn get_mut(&mut self) -> PoisonResult<&mut L::Inner> { if self.is_poisoned() { - Err(PoisonError::new(&mut self.inner)) + Err(PoisonError::new(self.inner.as_mut())) } else { - Ok(&mut self.inner) + Ok(self.inner.as_mut()) } } } |
