summaryrefslogtreecommitdiff
path: root/src/lockable.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockable.rs')
-rw-r--r--src/lockable.rs126
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