summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/collection/owned.rs10
-rw-r--r--src/collection/retry.rs22
-rw-r--r--src/lockable.rs124
-rw-r--r--src/poisonable/poisonable.rs2
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<L: Lockable> Lockable for OwnedLockCollection<L> {
}
}
+impl<L: LockableIntoInner> LockableIntoInner for OwnedLockCollection<L> {
+ type Inner = L::Inner;
+
+ fn into_inner(self) -> Self::Inner {
+ self.data.into_inner()
+ }
+}
+
unsafe impl<L: Sharable> Sharable for OwnedLockCollection<L> {}
unsafe impl<L: OwnedLockable> OwnedLockable for OwnedLockCollection<L> {}
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<L: Lockable> Lockable for RetryingLockCollection<L> {
}
}
+impl<L: LockableAsMut> LockableAsMut for RetryingLockCollection<L> {
+ type Inner<'a> = L::Inner<'a>
+ where
+ Self: 'a;
+
+ fn as_mut(&mut self) -> Self::Inner<'_> {
+ self.data.as_mut()
+ }
+}
+
+impl<L: LockableIntoInner> LockableIntoInner for RetryingLockCollection<L> {
+ type Inner = L::Inner;
+
+ fn into_inner(self) -> Self::Inner {
+ self.data.into_inner()
+ }
+}
+
unsafe impl<L: Sharable> Sharable for RetryingLockCollection<L> {}
unsafe impl<L: OwnedLockable> OwnedLockable for RetryingLockCollection<L> {}
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<T: Send, R: RawMutex + Send + Sync> LockableIntoInner for Mutex<T, R> {
}
impl<T: Send, R: RawMutex + Send + Sync> LockableAsMut for Mutex<T, R> {
- 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<T: Send, R: RawRwLock + Send + Sync> LockableIntoInner for RwLock<T, R> {
}
impl<T: Send, R: RawRwLock + Send + Sync> LockableAsMut for RwLock<T, R> {
- 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<T: Lockable> Lockable for &mut T {
}
}
+impl<T: LockableAsMut> 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<T: Sharable> Sharable for &mut T {}
unsafe impl<T: OwnedLockable> 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<T: Lockable> 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<T: Lockable> Lockable for Vec<T> {
}
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<T: Lockable, I: IntoIterator<Item=T>> Lockable for I
// but I think that'd require sealing up this trait
+impl<T: LockableAsMut, const N: usize> 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<T::Inner<'_>>; 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<T: LockableIntoInner, const N: usize> LockableIntoInner for [T; N] {
+ type Inner = [T::Inner; N];
+
+ fn into_inner(self) -> Self::Inner {
+ unsafe {
+ let mut guards = MaybeUninit::<[MaybeUninit<T::Inner>; 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<T: LockableAsMut + 'static> 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<T: LockableAsMut + 'static> LockableAsMut for Vec<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()
+ }
+}
+
+impl<T: LockableIntoInner> LockableIntoInner for Vec<T> {
+ type Inner = Box<[T::Inner]>;
+
+ fn into_inner(self) -> Self::Inner {
+ self.into_iter()
+ .map(LockableIntoInner::into_inner)
+ .collect()
+ }
+}
+
unsafe impl<T: Sharable, const N: usize> Sharable for [T; N] {}
unsafe impl<T: Sharable> Sharable for Box<[T]> {}
unsafe impl<T: Sharable> Sharable for Vec<T> {}
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<L: LockableAsMut + RawLock> Poisonable<L> {
/// *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<L::Inner<'_>> {
if self.is_poisoned() {
Err(PoisonError::new(self.inner.as_mut()))
} else {