summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/collection/boxed.rs14
-rw-r--r--src/collection/owned.rs20
-rw-r--r--src/collection/ref.rs14
-rw-r--r--src/collection/retry.rs20
-rw-r--r--src/lockable.rs309
-rw-r--r--src/mutex/mutex.rs8
-rw-r--r--src/poisonable/poisonable.rs13
-rw-r--r--src/rwlock.rs24
-rw-r--r--src/rwlock/read_lock.rs29
-rw-r--r--src/rwlock/rwlock.rs20
-rw-r--r--src/rwlock/write_lock.rs18
11 files changed, 235 insertions, 254 deletions
diff --git a/src/collection/boxed.rs b/src/collection/boxed.rs
index 6db0683..3766bed 100644
--- a/src/collection/boxed.rs
+++ b/src/collection/boxed.rs
@@ -62,11 +62,6 @@ unsafe impl<L: Lockable> Lockable for BoxedLockCollection<L> {
where
Self: 'g;
- type ReadGuard<'g>
- = L::ReadGuard<'g>
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
ptrs.extend(self.locks())
}
@@ -74,14 +69,19 @@ unsafe impl<L: Lockable> Lockable for BoxedLockCollection<L> {
unsafe fn guard(&self) -> Self::Guard<'_> {
self.data().guard()
}
+}
+
+unsafe impl<L: Sharable> Sharable for BoxedLockCollection<L> {
+ type ReadGuard<'g>
+ = L::ReadGuard<'g>
+ where
+ Self: 'g;
unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
self.data().read_guard()
}
}
-unsafe impl<L: Sharable> Sharable for BoxedLockCollection<L> {}
-
unsafe impl<L: OwnedLockable> OwnedLockable for BoxedLockCollection<L> {}
impl<L> IntoIterator for BoxedLockCollection<L>
diff --git a/src/collection/owned.rs b/src/collection/owned.rs
index 3ea08b5..714ff01 100644
--- a/src/collection/owned.rs
+++ b/src/collection/owned.rs
@@ -58,11 +58,6 @@ unsafe impl<L: Lockable> Lockable for OwnedLockCollection<L> {
where
Self: 'g;
- type ReadGuard<'g>
- = L::ReadGuard<'g>
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
self.data.get_ptrs(ptrs)
}
@@ -70,10 +65,6 @@ unsafe impl<L: Lockable> Lockable for OwnedLockCollection<L> {
unsafe fn guard(&self) -> Self::Guard<'_> {
self.data.guard()
}
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- self.data.read_guard()
- }
}
impl<L: LockableIntoInner> LockableIntoInner for OwnedLockCollection<L> {
@@ -84,7 +75,16 @@ impl<L: LockableIntoInner> LockableIntoInner for OwnedLockCollection<L> {
}
}
-unsafe impl<L: Sharable> Sharable for OwnedLockCollection<L> {}
+unsafe impl<L: Sharable> Sharable for OwnedLockCollection<L> {
+ type ReadGuard<'g>
+ = L::ReadGuard<'g>
+ where
+ Self: 'g;
+
+ unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
+ self.data.read_guard()
+ }
+}
unsafe impl<L: OwnedLockable> OwnedLockable for OwnedLockCollection<L> {}
diff --git a/src/collection/ref.rs b/src/collection/ref.rs
index 9e07860..a9fc915 100644
--- a/src/collection/ref.rs
+++ b/src/collection/ref.rs
@@ -86,11 +86,6 @@ unsafe impl<L: Lockable> Lockable for RefLockCollection<'_, L> {
where
Self: 'g;
- type ReadGuard<'g>
- = L::ReadGuard<'g>
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
ptrs.extend_from_slice(&self.locks);
}
@@ -98,14 +93,19 @@ unsafe impl<L: Lockable> Lockable for RefLockCollection<'_, L> {
unsafe fn guard(&self) -> Self::Guard<'_> {
self.data.guard()
}
+}
+
+unsafe impl<L: Sharable> Sharable for RefLockCollection<'_, L> {
+ type ReadGuard<'g>
+ = L::ReadGuard<'g>
+ where
+ Self: 'g;
unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
self.data.read_guard()
}
}
-unsafe impl<L: Sharable> Sharable for RefLockCollection<'_, L> {}
-
impl<L: Debug> Debug for RefLockCollection<'_, L> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(stringify!(RefLockCollection))
diff --git a/src/collection/retry.rs b/src/collection/retry.rs
index 42d86e5..0c44dea 100644
--- a/src/collection/retry.rs
+++ b/src/collection/retry.rs
@@ -219,11 +219,6 @@ unsafe impl<L: Lockable> Lockable for RetryingLockCollection<L> {
where
Self: 'g;
- type ReadGuard<'g>
- = L::ReadGuard<'g>
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
self.data.get_ptrs(ptrs)
}
@@ -231,10 +226,6 @@ unsafe impl<L: Lockable> Lockable for RetryingLockCollection<L> {
unsafe fn guard(&self) -> Self::Guard<'_> {
self.data.guard()
}
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- self.data.read_guard()
- }
}
impl<L: LockableAsMut> LockableAsMut for RetryingLockCollection<L> {
@@ -256,7 +247,16 @@ impl<L: LockableIntoInner> LockableIntoInner for RetryingLockCollection<L> {
}
}
-unsafe impl<L: Sharable> Sharable for RetryingLockCollection<L> {}
+unsafe impl<L: Sharable> Sharable for RetryingLockCollection<L> {
+ type ReadGuard<'g>
+ = L::ReadGuard<'g>
+ where
+ Self: 'g;
+
+ unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
+ self.data.read_guard()
+ }
+}
unsafe impl<L: OwnedLockable> OwnedLockable for RetryingLockCollection<L> {}
diff --git a/src/lockable.rs b/src/lockable.rs
index 78f008e..5cc7135 100644
--- a/src/lockable.rs
+++ b/src/lockable.rs
@@ -1,9 +1,5 @@
use std::mem::MaybeUninit;
-use crate::rwlock::{ReadLock, RwLockReadRef, RwLockWriteRef, WriteLock};
-
-use lock_api::RawRwLock;
-
/// A raw lock type that may be locked and unlocked
///
/// # Safety
@@ -116,11 +112,6 @@ pub unsafe trait Lockable {
where
Self: 'g;
- /// The shared guard type that does not hold a key
- type ReadGuard<'g>
- where
- Self: 'g;
-
/// Yields a list of references to the [`RawLock`]s contained within this
/// value.
///
@@ -139,17 +130,6 @@ pub unsafe trait Lockable {
/// unlocked until this guard is dropped.
#[must_use]
unsafe fn guard(&self) -> Self::Guard<'_>;
-
- /// Returns a guard that can be used to immutably access the underlying
- /// data.
- ///
- /// # Safety
- ///
- /// All locks given by calling [`Lockable::get_ptrs`] must be locked using
- /// [`RawLock::read`] before calling this function. The locks must not be
- /// unlocked until this guard is dropped.
- #[must_use]
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_>;
}
/// A trait which indicates that `into_inner` is a valid operation for a
@@ -190,14 +170,24 @@ pub trait LockableAsMut: Lockable {
fn as_mut(&mut self) -> Self::Inner<'_>;
}
-/// A marker trait to indicate that multiple readers can access the lock at a
-/// time.
-///
-/// # Safety
-///
-/// This type must only be implemented if the lock can be safely shared between
-/// multiple readers.
-pub unsafe trait Sharable: Lockable {}
+/// Allows a lock to be accessed by multiple readers.
+pub unsafe trait Sharable: Lockable {
+ /// The shared guard type that does not hold a key
+ type ReadGuard<'g>
+ where
+ Self: 'g;
+
+ /// Returns a guard that can be used to immutably access the underlying
+ /// data.
+ ///
+ /// # Safety
+ ///
+ /// All locks given by calling [`Lockable::get_ptrs`] must be locked using
+ /// [`RawLock::read`] before calling this function. The locks must not be
+ /// unlocked until this guard is dropped.
+ #[must_use]
+ unsafe fn read_guard(&self) -> Self::ReadGuard<'_>;
+}
/// A type that may be locked and unlocked, and is known to be the only valid
/// instance of the lock.
@@ -208,98 +198,38 @@ pub unsafe trait Sharable: Lockable {}
/// time, i.e., this must either be an owned value or a mutable reference.
pub unsafe trait OwnedLockable: Lockable {}
-unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for ReadLock<'_, T, R> {
- type Guard<'g>
- = RwLockReadRef<'g, T, R>
- where
- Self: 'g;
-
- type ReadGuard<'g>
- = RwLockReadRef<'g, T, R>
- where
- Self: 'g;
-
- fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
- ptrs.push(self.as_ref());
- }
-
- unsafe fn guard(&self) -> Self::Guard<'_> {
- RwLockReadRef::new(self.as_ref())
- }
-
- unsafe fn read_guard(&self) -> Self::Guard<'_> {
- RwLockReadRef::new(self.as_ref())
- }
-}
-
-unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for WriteLock<'_, T, R> {
+unsafe impl<T: Lockable> Lockable for &T {
type Guard<'g>
- = RwLockWriteRef<'g, T, R>
- where
- Self: 'g;
-
- type ReadGuard<'g>
- = RwLockWriteRef<'g, T, R>
+ = T::Guard<'g>
where
Self: 'g;
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
- ptrs.push(self.as_ref());
+ (*self).get_ptrs(ptrs);
}
unsafe fn guard(&self) -> Self::Guard<'_> {
- RwLockWriteRef::new(self.as_ref())
- }
-
- unsafe fn read_guard(&self) -> Self::Guard<'_> {
- RwLockWriteRef::new(self.as_ref())
+ (*self).guard()
}
}
-// Technically, the exclusive locks can also be shared, but there's currently
-// no way to express that. I don't think I want to ever express that.
-unsafe impl<T: Send, R: RawRwLock + Send + Sync> Sharable for ReadLock<'_, T, R> {}
-
-// Because both ReadLock and WriteLock hold references to RwLocks, they can't
-// implement OwnedLockable
-
-unsafe impl<T: Lockable> Lockable for &T {
- type Guard<'g>
- = T::Guard<'g>
- where
- Self: 'g;
-
+unsafe impl<T: Sharable> Sharable for &T {
type ReadGuard<'g>
= T::ReadGuard<'g>
where
Self: 'g;
- fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
- (*self).get_ptrs(ptrs);
- }
-
- unsafe fn guard(&self) -> Self::Guard<'_> {
- (*self).guard()
- }
-
unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
(*self).read_guard()
}
}
-unsafe impl<T: Sharable> Sharable for &T {}
-
unsafe impl<T: Lockable> Lockable for &mut T {
type Guard<'g>
= T::Guard<'g>
where
Self: 'g;
- type ReadGuard<'g>
- = T::ReadGuard<'g>
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
(**self).get_ptrs(ptrs)
}
@@ -307,10 +237,6 @@ unsafe impl<T: Lockable> Lockable for &mut T {
unsafe fn guard(&self) -> Self::Guard<'_> {
(**self).guard()
}
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- (**self).read_guard()
- }
}
impl<T: LockableAsMut> LockableAsMut for &mut T {
@@ -324,7 +250,16 @@ impl<T: LockableAsMut> LockableAsMut for &mut T {
}
}
-unsafe impl<T: Sharable> Sharable for &mut T {}
+unsafe impl<T: Sharable> Sharable for &mut T {
+ type ReadGuard<'g>
+ = T::ReadGuard<'g>
+ where
+ Self: 'g;
+
+ unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
+ (**self).read_guard()
+ }
+}
unsafe impl<T: OwnedLockable> OwnedLockable for &mut T {}
@@ -335,7 +270,7 @@ macro_rules! tuple_impls {
unsafe impl<$($generic: Lockable,)*> Lockable for ($($generic,)*) {
type Guard<'g> = ($($generic::Guard<'g>,)*) where Self: 'g;
- type ReadGuard<'g> = ($($generic::ReadGuard<'g>,)*) where Self: 'g;
+
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
self.0.get_ptrs(ptrs);
@@ -346,10 +281,6 @@ macro_rules! tuple_impls {
// I don't think any other way of doing it compiles
($(self.$value.guard(),)*)
}
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- ($(self.$value.read_guard(),)*)
- }
}
impl<$($generic: LockableAsMut,)*> LockableAsMut for ($($generic,)*) {
@@ -368,7 +299,13 @@ macro_rules! tuple_impls {
}
}
- unsafe impl<$($generic: Sharable,)*> Sharable for ($($generic,)*) {}
+ unsafe impl<$($generic: Sharable,)*> Sharable for ($($generic,)*) {
+ type ReadGuard<'g> = ($($generic::ReadGuard<'g>,)*) where Self: 'g;
+
+ unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
+ ($(self.$value.read_guard(),)*)
+ }
+ }
unsafe impl<$($generic: OwnedLockable,)*> OwnedLockable for ($($generic,)*) {}
};
@@ -388,11 +325,6 @@ unsafe impl<T: Lockable, const N: usize> Lockable for [T; N] {
where
Self: 'g;
- type ReadGuard<'g>
- = [T::ReadGuard<'g>; N]
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
for lock in self {
lock.get_ptrs(ptrs);
@@ -409,6 +341,46 @@ unsafe impl<T: Lockable, const N: usize> Lockable for [T; N] {
guards.map(|g| g.assume_init())
}
+}
+
+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())
+ }
+ }
+}
+
+unsafe impl<T: Sharable, const N: usize> Sharable for [T; N] {
+ type ReadGuard<'g>
+ = [T::ReadGuard<'g>; N]
+ where
+ Self: 'g;
unsafe fn read_guard<'g>(&'g self) -> Self::ReadGuard<'g> {
let mut guards = MaybeUninit::<[MaybeUninit<T::ReadGuard<'g>>; N]>::uninit().assume_init();
@@ -420,17 +392,14 @@ unsafe impl<T: Lockable, const N: usize> Lockable for [T; N] {
}
}
+unsafe impl<T: OwnedLockable, const N: usize> OwnedLockable for [T; N] {}
+
unsafe impl<T: Lockable> Lockable for Box<[T]> {
type Guard<'g>
= Box<[T::Guard<'g>]>
where
Self: 'g;
- type ReadGuard<'g>
- = Box<[T::ReadGuard<'g>]>
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
for lock in self.iter() {
lock.get_ptrs(ptrs);
@@ -440,86 +409,64 @@ unsafe impl<T: Lockable> Lockable for Box<[T]> {
unsafe fn guard(&self) -> Self::Guard<'_> {
self.iter().map(|lock| lock.guard()).collect()
}
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- self.iter().map(|lock| lock.read_guard()).collect()
- }
}
-unsafe impl<T: Lockable> Lockable for Vec<T> {
- // There's no reason why I'd ever want to extend a list of lock guards
- type Guard<'g>
- = Box<[T::Guard<'g>]>
+impl<T: LockableAsMut + 'static> LockableAsMut for Box<[T]> {
+ type Inner<'a>
+ = Box<[T::Inner<'a>]>
where
- Self: 'g;
+ Self: 'a;
+
+ fn as_mut(&mut self) -> Self::Inner<'_> {
+ self.iter_mut().map(LockableAsMut::as_mut).collect()
+ }
+}
+unsafe impl<T: Sharable> Sharable for Box<[T]> {
type ReadGuard<'g>
= Box<[T::ReadGuard<'g>]>
where
Self: 'g;
- fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
- for lock in self {
- lock.get_ptrs(ptrs);
- }
- }
-
- unsafe fn guard(&self) -> Self::Guard<'_> {
- self.iter().map(|lock| lock.guard()).collect()
- }
-
unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
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]
+unsafe impl<T: Sharable> Sharable for Vec<T> {
+ type ReadGuard<'g>
+ = Box<[T::ReadGuard<'g>]>
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());
- }
+ Self: 'g;
- guards.map(|g| g.assume_init())
- }
+ unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
+ self.iter().map(|lock| lock.read_guard()).collect()
}
}
-impl<T: LockableIntoInner, const N: usize> LockableIntoInner for [T; N] {
- type Inner = [T::Inner; N];
+unsafe impl<T: OwnedLockable> OwnedLockable for Box<[T]> {}
- 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());
- }
+unsafe impl<T: Lockable> Lockable for Vec<T> {
+ // There's no reason why I'd ever want to extend a list of lock guards
+ type Guard<'g>
+ = Box<[T::Guard<'g>]>
+ where
+ Self: 'g;
- guards.map(|g| g.assume_init())
+ fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
+ for lock in self {
+ lock.get_ptrs(ptrs);
}
}
-}
-
-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()
+ unsafe fn guard(&self) -> Self::Guard<'_> {
+ self.iter().map(|lock| lock.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
+
// TODO: using edition 2024, impl LockableIntoInner for Box<[T]>
impl<T: LockableAsMut + 'static> LockableAsMut for Vec<T> {
@@ -543,12 +490,6 @@ impl<T: LockableIntoInner> LockableIntoInner for Vec<T> {
}
}
-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> {}
-
-unsafe impl<T: OwnedLockable, const N: usize> OwnedLockable for [T; N] {}
-unsafe impl<T: OwnedLockable> OwnedLockable for Box<[T]> {}
unsafe impl<T: OwnedLockable> OwnedLockable for Vec<T> {}
#[cfg(test)]
@@ -568,28 +509,6 @@ mod tests {
}
#[test]
- fn read_lock_get_ptrs() {
- let rwlock = RwLock::new(5);
- let readlock = ReadLock::new(&rwlock);
- let mut lock_ptrs = Vec::new();
- readlock.get_ptrs(&mut lock_ptrs);
-
- assert_eq!(lock_ptrs.len(), 1);
- assert!(std::ptr::addr_eq(lock_ptrs[0], &rwlock));
- }
-
- #[test]
- fn write_lock_get_ptrs() {
- let rwlock = RwLock::new(5);
- let writelock = WriteLock::new(&rwlock);
- let mut lock_ptrs = Vec::new();
- writelock.get_ptrs(&mut lock_ptrs);
-
- assert_eq!(lock_ptrs.len(), 1);
- assert!(std::ptr::addr_eq(lock_ptrs[0], &rwlock));
- }
-
- #[test]
fn array_get_ptrs_empty() {
let locks: [Mutex<()>; 0] = [];
let mut lock_ptrs = Vec::new();
diff --git a/src/mutex/mutex.rs b/src/mutex/mutex.rs
index d744891..27a215f 100644
--- a/src/mutex/mutex.rs
+++ b/src/mutex/mutex.rs
@@ -61,10 +61,6 @@ unsafe impl<T: Send, R: RawMutex + Send + Sync> Lockable for Mutex<T, R> {
= MutexRef<'g, T, R>
where
Self: 'g;
- type ReadGuard<'g>
- = MutexRef<'g, T, R>
- where
- Self: 'g;
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
ptrs.push(self);
@@ -73,10 +69,6 @@ unsafe impl<T: Send, R: RawMutex + Send + Sync> Lockable for Mutex<T, R> {
unsafe fn guard(&self) -> Self::Guard<'_> {
MutexRef::new(self)
}
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- MutexRef::new(self)
- }
}
impl<T: Send, R: RawMutex + Send + Sync> LockableIntoInner for Mutex<T, R> {
diff --git a/src/poisonable/poisonable.rs b/src/poisonable/poisonable.rs
index 0fc66a8..57436eb 100644
--- a/src/poisonable/poisonable.rs
+++ b/src/poisonable/poisonable.rs
@@ -47,11 +47,6 @@ unsafe impl<L: Lockable> Lockable for Poisonable<L> {
where
Self: 'g;
- type ReadGuard<'g>
- = PoisonResult<PoisonRef<'g, L::ReadGuard<'g>>>
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
self.inner.get_ptrs(ptrs)
}
@@ -65,6 +60,13 @@ unsafe impl<L: Lockable> Lockable for Poisonable<L> {
Err(PoisonError::new(ref_guard))
}
}
+}
+
+unsafe impl<L: Sharable> Sharable for Poisonable<L> {
+ type ReadGuard<'g>
+ = PoisonResult<PoisonRef<'g, L::ReadGuard<'g>>>
+ where
+ Self: 'g;
unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
let ref_guard = PoisonRef::new(&self.poisoned, self.inner.read_guard());
@@ -77,7 +79,6 @@ unsafe impl<L: Lockable> Lockable for Poisonable<L> {
}
}
-unsafe impl<L: Sharable> Sharable for Poisonable<L> {}
unsafe impl<L: OwnedLockable> OwnedLockable for Poisonable<L> {}
impl<L> From<L> for Poisonable<L> {
diff --git a/src/rwlock.rs b/src/rwlock.rs
index 64dc82b..1425b54 100644
--- a/src/rwlock.rs
+++ b/src/rwlock.rs
@@ -116,6 +116,8 @@ pub struct RwLockWriteGuard<'a, 'key, T: ?Sized, Key: Keyable + 'key, R: RawRwLo
#[cfg(test)]
mod tests {
+ use crate::lockable::Lockable;
+ use crate::RwLock;
use crate::ThreadKey;
use super::*;
@@ -148,6 +150,28 @@ mod tests {
}
#[test]
+ fn read_lock_get_ptrs() {
+ let rwlock = RwLock::new(5);
+ let readlock = ReadLock::new(&rwlock);
+ let mut lock_ptrs = Vec::new();
+ readlock.get_ptrs(&mut lock_ptrs);
+
+ assert_eq!(lock_ptrs.len(), 1);
+ assert!(std::ptr::addr_eq(lock_ptrs[0], &rwlock));
+ }
+
+ #[test]
+ fn write_lock_get_ptrs() {
+ let rwlock = RwLock::new(5);
+ let writelock = WriteLock::new(&rwlock);
+ let mut lock_ptrs = Vec::new();
+ writelock.get_ptrs(&mut lock_ptrs);
+
+ assert_eq!(lock_ptrs.len(), 1);
+ assert!(std::ptr::addr_eq(lock_ptrs[0], &rwlock));
+ }
+
+ #[test]
fn locked_after_read() {
let key = ThreadKey::get().unwrap();
let lock: crate::RwLock<_> = RwLock::new("Hello, world!");
diff --git a/src/rwlock/read_lock.rs b/src/rwlock/read_lock.rs
index e518cf3..34e3f5e 100644
--- a/src/rwlock/read_lock.rs
+++ b/src/rwlock/read_lock.rs
@@ -3,9 +3,38 @@ use std::fmt::Debug;
use lock_api::RawRwLock;
use crate::key::Keyable;
+use crate::lockable::{Lockable, RawLock, Sharable};
use super::{ReadLock, RwLock, RwLockReadGuard, RwLockReadRef};
+unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for ReadLock<'_, T, R> {
+ type Guard<'g>
+ = RwLockReadRef<'g, T, R>
+ where
+ Self: 'g;
+
+ fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
+ ptrs.push(self.as_ref());
+ }
+
+ unsafe fn guard(&self) -> Self::Guard<'_> {
+ RwLockReadRef::new(self.as_ref())
+ }
+}
+
+// Technically, the exclusive locks can also be shared, but there's currently
+// no way to express that. I don't think I want to ever express that.
+unsafe impl<T: Send, R: RawRwLock + Send + Sync> Sharable for ReadLock<'_, T, R> {
+ type ReadGuard<'g>
+ = RwLockReadRef<'g, T, R>
+ where
+ Self: 'g;
+
+ unsafe fn read_guard(&self) -> Self::Guard<'_> {
+ RwLockReadRef::new(self.as_ref())
+ }
+}
+
impl<T: ?Sized + Debug, R: RawRwLock> Debug for ReadLock<'_, T, R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// safety: this is just a try lock, and the value is dropped
diff --git a/src/rwlock/rwlock.rs b/src/rwlock/rwlock.rs
index b5dea75..2c9ba22 100644
--- a/src/rwlock/rwlock.rs
+++ b/src/rwlock/rwlock.rs
@@ -79,11 +79,6 @@ unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for RwLock<T, R> {
where
Self: 'g;
- type ReadGuard<'g>
- = RwLockReadRef<'g, T, R>
- where
- Self: 'g;
-
fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
ptrs.push(self);
}
@@ -91,10 +86,6 @@ unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for RwLock<T, R> {
unsafe fn guard(&self) -> Self::Guard<'_> {
RwLockWriteRef::new(self)
}
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- RwLockReadRef::new(self)
- }
}
impl<T: Send, R: RawRwLock + Send + Sync> LockableIntoInner for RwLock<T, R> {
@@ -116,7 +107,16 @@ impl<T: Send, R: RawRwLock + Send + Sync> LockableAsMut for RwLock<T, R> {
}
}
-unsafe impl<T: Send, R: RawRwLock + Send + Sync> Sharable for RwLock<T, R> {}
+unsafe impl<T: Send, R: RawRwLock + Send + Sync> Sharable for RwLock<T, R> {
+ type ReadGuard<'g>
+ = RwLockReadRef<'g, T, R>
+ where
+ Self: 'g;
+
+ unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
+ RwLockReadRef::new(self)
+ }
+}
unsafe impl<T: Send, R: RawRwLock + Send + Sync> OwnedLockable for RwLock<T, R> {}
diff --git a/src/rwlock/write_lock.rs b/src/rwlock/write_lock.rs
index ba05e87..27fa1d2 100644
--- a/src/rwlock/write_lock.rs
+++ b/src/rwlock/write_lock.rs
@@ -3,8 +3,24 @@ use std::fmt::Debug;
use lock_api::RawRwLock;
use crate::key::Keyable;
+use crate::lockable::{Lockable, RawLock};
-use super::{RwLock, RwLockWriteGuard, WriteLock};
+use super::{RwLock, RwLockWriteGuard, RwLockWriteRef, WriteLock};
+
+unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for WriteLock<'_, T, R> {
+ type Guard<'g>
+ = RwLockWriteRef<'g, T, R>
+ where
+ Self: 'g;
+
+ fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn RawLock>) {
+ ptrs.push(self.as_ref());
+ }
+
+ unsafe fn guard(&self) -> Self::Guard<'_> {
+ RwLockWriteRef::new(self.as_ref())
+ }
+}
impl<T: ?Sized + Debug, R: RawRwLock> Debug for WriteLock<'_, T, R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {