diff options
| -rw-r--r-- | src/collection/boxed.rs | 14 | ||||
| -rw-r--r-- | src/collection/owned.rs | 20 | ||||
| -rw-r--r-- | src/collection/ref.rs | 14 | ||||
| -rw-r--r-- | src/collection/retry.rs | 20 | ||||
| -rw-r--r-- | src/lockable.rs | 309 | ||||
| -rw-r--r-- | src/mutex/mutex.rs | 8 | ||||
| -rw-r--r-- | src/poisonable/poisonable.rs | 13 | ||||
| -rw-r--r-- | src/rwlock.rs | 24 | ||||
| -rw-r--r-- | src/rwlock/read_lock.rs | 29 | ||||
| -rw-r--r-- | src/rwlock/rwlock.rs | 20 | ||||
| -rw-r--r-- | src/rwlock/write_lock.rs | 18 |
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 { |
