diff options
Diffstat (limited to 'src/lockable.rs')
| -rw-r--r-- | src/lockable.rs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/lockable.rs b/src/lockable.rs index 4f7cfe5..f125c02 100644 --- a/src/lockable.rs +++ b/src/lockable.rs @@ -111,6 +111,10 @@ pub unsafe trait Lockable { where Self: 'g; + type DataMut<'a> + where + Self: 'a; + /// Yields a list of references to the [`RawLock`]s contained within this /// value. /// @@ -129,6 +133,9 @@ pub unsafe trait Lockable { /// unlocked until this guard is dropped. #[must_use] unsafe fn guard(&self) -> Self::Guard<'_>; + + #[must_use] + unsafe fn data_mut(&self) -> Self::DataMut<'_>; } /// Allows a lock to be accessed by multiple readers. @@ -145,6 +152,10 @@ pub unsafe trait Sharable: Lockable { where Self: 'g; + type DataRef<'a> + where + Self: 'a; + /// Returns a guard that can be used to immutably access the underlying /// data. /// @@ -155,6 +166,9 @@ pub unsafe trait Sharable: Lockable { /// unlocked until this guard is dropped. #[must_use] unsafe fn read_guard(&self) -> Self::ReadGuard<'_>; + + #[must_use] + unsafe fn data_ref(&self) -> Self::DataRef<'_>; } /// A type that may be locked and unlocked, and is known to be the only valid @@ -210,6 +224,11 @@ unsafe impl<T: Lockable> Lockable for &T { where Self: 'g; + type DataMut<'a> + = T::DataMut<'a> + where + Self: 'a; + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) { (*self).get_ptrs(ptrs); } @@ -217,6 +236,10 @@ unsafe impl<T: Lockable> Lockable for &T { unsafe fn guard(&self) -> Self::Guard<'_> { (*self).guard() } + + unsafe fn data_mut(&self) -> Self::DataMut<'_> { + (*self).data_mut() + } } unsafe impl<T: Sharable> Sharable for &T { @@ -225,9 +248,18 @@ unsafe impl<T: Sharable> Sharable for &T { where Self: 'g; + type DataRef<'a> + = T::DataRef<'a> + where + Self: 'a; + unsafe fn read_guard(&self) -> Self::ReadGuard<'_> { (*self).read_guard() } + + unsafe fn data_ref(&self) -> Self::DataRef<'_> { + (*self).data_ref() + } } unsafe impl<T: Lockable> Lockable for &mut T { @@ -236,6 +268,11 @@ unsafe impl<T: Lockable> Lockable for &mut T { where Self: 'g; + type DataMut<'a> + = T::DataMut<'a> + where + Self: 'a; + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) { (**self).get_ptrs(ptrs) } @@ -243,6 +280,10 @@ unsafe impl<T: Lockable> Lockable for &mut T { unsafe fn guard(&self) -> Self::Guard<'_> { (**self).guard() } + + unsafe fn data_mut(&self) -> Self::DataMut<'_> { + (**self).data_mut() + } } impl<T: LockableGetMut> LockableGetMut for &mut T { @@ -262,9 +303,18 @@ unsafe impl<T: Sharable> Sharable for &mut T { where Self: 'g; + type DataRef<'a> + = T::DataRef<'a> + where + Self: 'a; + unsafe fn read_guard(&self) -> Self::ReadGuard<'_> { (**self).read_guard() } + + unsafe fn data_ref(&self) -> Self::DataRef<'_> { + (**self).data_ref() + } } unsafe impl<T: OwnedLockable> OwnedLockable for &mut T {} @@ -276,6 +326,8 @@ macro_rules! tuple_impls { unsafe impl<$($generic: Lockable,)*> Lockable for ($($generic,)*) { type Guard<'g> = ($($generic::Guard<'g>,)*) where Self: 'g; + type DataMut<'a> = ($($generic::DataMut<'a>,)*) where Self: 'a; + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) { $(self.$value.get_ptrs(ptrs));* } @@ -285,6 +337,10 @@ macro_rules! tuple_impls { // I don't think any other way of doing it compiles ($(self.$value.guard(),)*) } + + unsafe fn data_mut(&self) -> Self::DataMut<'_> { + ($(self.$value.data_mut(),)*) + } } impl<$($generic: LockableGetMut,)*> LockableGetMut for ($($generic,)*) { @@ -306,9 +362,15 @@ macro_rules! tuple_impls { unsafe impl<$($generic: Sharable,)*> Sharable for ($($generic,)*) { type ReadGuard<'g> = ($($generic::ReadGuard<'g>,)*) where Self: 'g; + type DataRef<'a> = ($($generic::DataRef<'a>,)*) where Self: 'a; + unsafe fn read_guard(&self) -> Self::ReadGuard<'_> { ($(self.$value.read_guard(),)*) } + + unsafe fn data_ref(&self) -> Self::DataRef<'_> { + ($(self.$value.data_ref(),)*) + } } unsafe impl<$($generic: OwnedLockable,)*> OwnedLockable for ($($generic,)*) {} @@ -329,6 +391,11 @@ unsafe impl<T: Lockable, const N: usize> Lockable for [T; N] { where Self: 'g; + type DataMut<'a> + = [T::DataMut<'a>; N] + where + Self: 'a; + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) { for lock in self { lock.get_ptrs(ptrs); @@ -345,6 +412,15 @@ unsafe impl<T: Lockable, const N: usize> Lockable for [T; N] { guards.map(|g| g.assume_init()) } + + unsafe fn data_mut<'a>(&'a self) -> Self::DataMut<'a> { + let mut guards = MaybeUninit::<[MaybeUninit<T::DataMut<'a>>; N]>::uninit().assume_init(); + for i in 0..N { + guards[i].write(self[i].data_mut()); + } + + guards.map(|g| g.assume_init()) + } } impl<T: LockableGetMut, const N: usize> LockableGetMut for [T; N] { @@ -386,6 +462,11 @@ unsafe impl<T: Sharable, const N: usize> Sharable for [T; N] { where Self: 'g; + type DataRef<'a> + = [T::DataRef<'a>; N] + where + Self: 'a; + unsafe fn read_guard<'g>(&'g self) -> Self::ReadGuard<'g> { let mut guards = MaybeUninit::<[MaybeUninit<T::ReadGuard<'g>>; N]>::uninit().assume_init(); for i in 0..N { @@ -394,6 +475,15 @@ unsafe impl<T: Sharable, const N: usize> Sharable for [T; N] { guards.map(|g| g.assume_init()) } + + unsafe fn data_ref<'a>(&'a self) -> Self::DataRef<'a> { + let mut guards = MaybeUninit::<[MaybeUninit<T::DataRef<'a>>; N]>::uninit().assume_init(); + for i in 0..N { + guards[i].write(self[i].data_ref()); + } + + guards.map(|g| g.assume_init()) + } } unsafe impl<T: OwnedLockable, const N: usize> OwnedLockable for [T; N] {} @@ -404,6 +494,11 @@ unsafe impl<T: Lockable> Lockable for Box<[T]> { where Self: 'g; + type DataMut<'a> + = Box<[T::DataMut<'a>]> + where + Self: 'a; + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) { for lock in self { lock.get_ptrs(ptrs); @@ -413,6 +508,10 @@ unsafe impl<T: Lockable> Lockable for Box<[T]> { unsafe fn guard(&self) -> Self::Guard<'_> { self.iter().map(|lock| lock.guard()).collect() } + + unsafe fn data_mut(&self) -> Self::DataMut<'_> { + self.iter().map(|lock| lock.data_mut()).collect() + } } impl<T: LockableGetMut + 'static> LockableGetMut for Box<[T]> { @@ -432,9 +531,18 @@ unsafe impl<T: Sharable> Sharable for Box<[T]> { where Self: 'g; + type DataRef<'a> + = Box<[T::DataRef<'a>]> + where + Self: 'a; + unsafe fn read_guard(&self) -> Self::ReadGuard<'_> { self.iter().map(|lock| lock.read_guard()).collect() } + + unsafe fn data_ref(&self) -> Self::DataRef<'_> { + self.iter().map(|lock| lock.data_ref()).collect() + } } unsafe impl<T: Sharable> Sharable for Vec<T> { @@ -443,9 +551,18 @@ unsafe impl<T: Sharable> Sharable for Vec<T> { where Self: 'g; + type DataRef<'a> + = Box<[T::DataRef<'a>]> + where + Self: 'a; + unsafe fn read_guard(&self) -> Self::ReadGuard<'_> { self.iter().map(|lock| lock.read_guard()).collect() } + + unsafe fn data_ref(&self) -> Self::DataRef<'_> { + self.iter().map(|lock| lock.data_ref()).collect() + } } unsafe impl<T: OwnedLockable> OwnedLockable for Box<[T]> {} @@ -457,6 +574,11 @@ unsafe impl<T: Lockable> Lockable for Vec<T> { where Self: 'g; + type DataMut<'a> + = Box<[T::DataMut<'a>]> + where + Self: 'a; + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) { for lock in self { lock.get_ptrs(ptrs); @@ -466,6 +588,10 @@ unsafe impl<T: Lockable> Lockable for Vec<T> { unsafe fn guard(&self) -> Self::Guard<'_> { self.iter().map(|lock| lock.guard()).collect() } + + unsafe fn data_mut(&self) -> Self::DataMut<'_> { + self.iter().map(|lock| lock.data_mut()).collect() + } } // I'd make a generic impl<T: Lockable, I: IntoIterator<Item=T>> Lockable for I |
