From 0140f58043a2a00312d31907253cc718985e1e6c Mon Sep 17 00:00:00 2001 From: Botahamec Date: Fri, 27 Sep 2024 21:48:35 -0400 Subject: More implementations of LockableIntoInner and LockableAsMut --- src/collection/owned.rs | 10 +++- src/collection/retry.rs | 22 +++++++- src/lockable.rs | 124 ++++++++++++++++++++++++++++++++----------- src/poisonable/poisonable.rs | 2 +- 4 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/collection/owned.rs b/src/collection/owned.rs index 2b6e974..f2b6cc9 100644 --- a/src/collection/owned.rs +++ b/src/collection/owned.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use crate::lockable::{Lockable, OwnedLockable, RawLock, Sharable}; +use crate::lockable::{Lockable, LockableIntoInner, OwnedLockable, RawLock, Sharable}; use crate::Keyable; use super::{utils, LockGuard, OwnedLockCollection}; @@ -69,6 +69,14 @@ unsafe impl Lockable for OwnedLockCollection { } } +impl LockableIntoInner for OwnedLockCollection { + type Inner = L::Inner; + + fn into_inner(self) -> Self::Inner { + self.data.into_inner() + } +} + unsafe impl Sharable for OwnedLockCollection {} unsafe impl OwnedLockable for OwnedLockCollection {} diff --git a/src/collection/retry.rs b/src/collection/retry.rs index b73788a..7aa4ef4 100644 --- a/src/collection/retry.rs +++ b/src/collection/retry.rs @@ -1,4 +1,6 @@ -use crate::lockable::{Lockable, OwnedLockable, RawLock, Sharable}; +use crate::lockable::{ + Lockable, LockableAsMut, LockableIntoInner, OwnedLockable, RawLock, Sharable, +}; use crate::Keyable; use std::collections::HashSet; @@ -174,6 +176,24 @@ unsafe impl Lockable for RetryingLockCollection { } } +impl LockableAsMut for RetryingLockCollection { + type Inner<'a> = L::Inner<'a> + where + Self: 'a; + + fn as_mut(&mut self) -> Self::Inner<'_> { + self.data.as_mut() + } +} + +impl LockableIntoInner for RetryingLockCollection { + type Inner = L::Inner; + + fn into_inner(self) -> Self::Inner { + self.data.into_inner() + } +} + unsafe impl Sharable for RetryingLockCollection {} unsafe impl OwnedLockable for RetryingLockCollection {} diff --git a/src/lockable.rs b/src/lockable.rs index e32fccd..6d8e7b4 100644 --- a/src/lockable.rs +++ b/src/lockable.rs @@ -181,10 +181,12 @@ pub trait LockableIntoInner: Lockable { /// [`Poisonable::get_mut`]: `crate::poisonable::Poisonable::get_mut` pub trait LockableAsMut: Lockable { /// The inner type that is behind the lock - type Inner; + type Inner<'a> + where + Self: 'a; /// Returns a mutable reference to the underlying data. - fn as_mut(&mut self) -> &mut Self::Inner; + fn as_mut(&mut self) -> Self::Inner<'_>; } /// A marker trait to indicate that multiple readers can access the lock at a @@ -303,9 +305,9 @@ impl LockableIntoInner for Mutex { } impl LockableAsMut for Mutex { - type Inner = T; + type Inner<'a> = &'a mut T where Self: 'a; - fn as_mut(&mut self) -> &mut Self::Inner { + fn as_mut(&mut self) -> Self::Inner<'_> { self.get_mut() } } @@ -319,9 +321,9 @@ impl LockableIntoInner for RwLock { } impl LockableAsMut for RwLock { - type Inner = T; + type Inner<'a> = &'a mut T where Self: 'a; - fn as_mut(&mut self) -> &mut Self::Inner { + fn as_mut(&mut self) -> Self::Inner<'_> { AsMut::as_mut(self) } } @@ -413,6 +415,14 @@ unsafe impl Lockable for &mut T { } } +impl LockableAsMut for &mut T { + type Inner<'a> = T::Inner<'a> where Self: 'a; + + fn as_mut(&mut self) -> Self::Inner<'_> { + (*self).as_mut() + } +} + unsafe impl Sharable for &mut T {} unsafe impl OwnedLockable for &mut T {} @@ -441,6 +451,22 @@ macro_rules! tuple_impls { } } + impl<$($generic: LockableAsMut,)*> LockableAsMut for ($($generic,)*) { + type Inner<'a> = ($($generic::Inner<'a>,)*) where Self: 'a; + + fn as_mut(&mut self) -> Self::Inner<'_> { + ($(self.$value.as_mut(),)*) + } + } + + impl<$($generic: LockableIntoInner,)*> LockableIntoInner for ($($generic,)*) { + type Inner = ($($generic::Inner,)*); + + fn into_inner(self) -> Self::Inner { + ($(self.$value.into_inner(),)*) + } + } + unsafe impl<$($generic: Sharable,)*> Sharable for ($($generic,)*) {} unsafe impl<$($generic: OwnedLockable,)*> OwnedLockable for ($($generic,)*) {} @@ -499,21 +525,11 @@ unsafe impl Lockable for Box<[T]> { } unsafe fn guard(&self) -> Self::Guard<'_> { - let mut guards = Vec::new(); - for lock in self.iter() { - guards.push(lock.guard()); - } - - guards.into_boxed_slice() + self.iter().map(|lock| lock.guard()).collect() } unsafe fn read_guard(&self) -> Self::ReadGuard<'_> { - let mut guards = Vec::new(); - for lock in self.iter() { - guards.push(lock.read_guard()); - } - - guards.into_boxed_slice() + self.iter().map(|lock| lock.read_guard()).collect() } } @@ -530,27 +546,75 @@ unsafe impl Lockable for Vec { } unsafe fn guard(&self) -> Self::Guard<'_> { - let mut guards = Vec::new(); - for lock in self { - guards.push(lock.guard()); - } - - guards.into_boxed_slice() + self.iter().map(|lock| lock.guard()).collect() } unsafe fn read_guard(&self) -> Self::ReadGuard<'_> { - let mut guards = Vec::new(); - for lock in self { - guards.push(lock.read_guard()); - } - - guards.into_boxed_slice() + self.iter().map(|lock| lock.read_guard()).collect() } } // I'd make a generic impl> Lockable for I // but I think that'd require sealing up this trait +impl LockableAsMut for [T; N] { + type Inner<'a> = [T::Inner<'a>; N] where Self: 'a; + + fn as_mut(&mut self) -> Self::Inner<'_> { + unsafe { + let mut guards = MaybeUninit::<[MaybeUninit>; N]>::uninit().assume_init(); + for (i, lock) in self.iter_mut().enumerate() { + guards[i].write(lock.as_mut()); + } + + guards.map(|g| g.assume_init()) + } + } +} + +impl LockableIntoInner for [T; N] { + type Inner = [T::Inner; N]; + + fn into_inner(self) -> Self::Inner { + unsafe { + let mut guards = MaybeUninit::<[MaybeUninit; N]>::uninit().assume_init(); + for (i, lock) in self.into_iter().enumerate() { + guards[i].write(lock.into_inner()); + } + + guards.map(|g| g.assume_init()) + } + } +} + +impl LockableAsMut for Box<[T]> { + type Inner<'a> = Box<[T::Inner<'a>]> where Self: 'a; + + fn as_mut(&mut self) -> Self::Inner<'_> { + self.iter_mut().map(LockableAsMut::as_mut).collect() + } +} + +// TODO: using edition 2024, impl LockableIntoInner for Box<[T]> + +impl LockableAsMut for Vec { + type Inner<'a> = Box<[T::Inner<'a>]> where Self: 'a; + + fn as_mut(&mut self) -> Self::Inner<'_> { + self.iter_mut().map(LockableAsMut::as_mut).collect() + } +} + +impl LockableIntoInner for Vec { + type Inner = Box<[T::Inner]>; + + fn into_inner(self) -> Self::Inner { + self.into_iter() + .map(LockableIntoInner::into_inner) + .collect() + } +} + unsafe impl Sharable for [T; N] {} unsafe impl Sharable for Box<[T]> {} unsafe impl Sharable for Vec {} diff --git a/src/poisonable/poisonable.rs b/src/poisonable/poisonable.rs index 4c64884..61264ef 100644 --- a/src/poisonable/poisonable.rs +++ b/src/poisonable/poisonable.rs @@ -365,7 +365,7 @@ impl Poisonable { /// *mutex.get_mut().unwrap() = 10; /// assert_eq!(*mutex.lock(key).unwrap(), 10); /// ``` - pub fn get_mut(&mut self) -> PoisonResult<&mut L::Inner> { + pub fn get_mut(&mut self) -> PoisonResult> { if self.is_poisoned() { Err(PoisonError::new(self.inner.as_mut())) } else { -- cgit v1.2.3