From 801a870467af4059d2abdc67f2899edebb1f6d6c Mon Sep 17 00:00:00 2001 From: Mica White Date: Sat, 16 Mar 2024 12:41:27 -0400 Subject: retry lock collection --- src/lockable.rs | 274 +++++++++++++++++++++++++++----------------------------- 1 file changed, 131 insertions(+), 143 deletions(-) (limited to 'src/lockable.rs') diff --git a/src/lockable.rs b/src/lockable.rs index a09b84b..fe14e8c 100644 --- a/src/lockable.rs +++ b/src/lockable.rs @@ -47,14 +47,16 @@ pub unsafe trait Lock: Send + Sync { unsafe fn unlock(&self); } -pub unsafe trait Lockable<'a> { +pub unsafe trait Lockable { /// The guard returned that does not hold a key - type Guard; + type Guard<'g> + where + Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>); + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>); #[must_use] - unsafe fn guard(&'a self) -> Self::Guard; + unsafe fn guard(&self) -> Self::Guard<'_>; } /// A type that may be locked and unlocked, and is known to be the only valid @@ -64,7 +66,7 @@ pub unsafe trait Lockable<'a> { /// /// There must not be any two values which can unlock the value at the same /// time, i.e., this must either be an owned value or a mutable reference. -pub unsafe trait OwnedLockable<'a>: Lockable<'a> {} +pub unsafe trait OwnedLockable: Lockable {} unsafe impl Lock for Mutex { unsafe fn lock(&self) { @@ -94,138 +96,134 @@ unsafe impl Lock for RwLock { } } -unsafe impl<'a, T: Send + 'a, R: RawMutex + Send + Sync + 'a> Lockable<'a> for Mutex { - type Guard = MutexRef<'a, T, R>; +unsafe impl Lockable for Mutex { + type Guard<'g> = MutexRef<'g, T, R> where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { ptrs.push(self); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { MutexRef::new(self) } } -unsafe impl<'a, T: Send + 'a, R: RawRwLock + Send + Sync + 'a> Lockable<'a> for RwLock { - type Guard = RwLockWriteRef<'a, T, R>; +unsafe impl Lockable for RwLock { + type Guard<'g> = RwLockWriteRef<'g, T, R> where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { ptrs.push(self); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { RwLockWriteRef::new(self) } } -unsafe impl<'a, T: Send + 'a, R: RawMutex + Send + Sync + 'a> OwnedLockable<'a> for Mutex {} +unsafe impl OwnedLockable for Mutex {} -unsafe impl<'a, T: Send + 'a, R: RawRwLock + Send + Sync + 'a> OwnedLockable<'a> for RwLock {} +unsafe impl OwnedLockable for RwLock {} -unsafe impl<'a, T: Send + 'a, R: RawRwLock + Send + Sync + 'a> Lockable<'a> for ReadLock<'a, T, R> { - type Guard = RwLockReadRef<'a, T, R>; +unsafe impl<'r, T: Send + 'r, R: RawRwLock + Send + Sync + 'r> Lockable for ReadLock<'r, T, R> { + type Guard<'g> = RwLockReadRef<'g, T, R> where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { ptrs.push(self.as_ref()); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { RwLockReadRef::new(self.as_ref()) } } -unsafe impl<'a, T: Send + 'a, R: RawRwLock + Send + Sync + 'a> Lockable<'a> - for WriteLock<'a, T, R> -{ - type Guard = RwLockWriteRef<'a, T, R>; +unsafe impl<'r, T: Send + 'r, R: RawRwLock + Send + Sync + 'r> Lockable for WriteLock<'r, T, R> { + type Guard<'g> = RwLockWriteRef<'g, T, R> where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { ptrs.push(self.as_ref()); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { RwLockWriteRef::new(self.as_ref()) } } -unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &'a T { - type Guard = T::Guard; +unsafe impl Lockable for &T { + type Guard<'g> = T::Guard<'g> where Self: 'g; - fn get_ptrs(&self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { (*self).get_ptrs(ptrs); } - unsafe fn guard(&self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { (*self).guard() } } -unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &mut T { - type Guard = T::Guard; +unsafe impl Lockable for &mut T { + type Guard<'g> = T::Guard<'g> where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { (**self).get_ptrs(ptrs) } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { (**self).guard() } } -unsafe impl<'a, T: OwnedLockable<'a>> OwnedLockable<'a> for &mut T {} +unsafe impl OwnedLockable for &mut T {} -unsafe impl<'a, A: Lockable<'a>> Lockable<'a> for (A,) { - type Guard = (A::Guard,); +unsafe impl Lockable for (A,) { + type Guard<'g> = (A::Guard<'g>,) where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { self.0.get_ptrs(ptrs); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { (self.0.guard(),) } } -unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>> Lockable<'a> for (A, B) { - type Guard = (A::Guard, B::Guard); +unsafe impl Lockable for (A, B) { + type Guard<'g> = (A::Guard<'g>, B::Guard<'g>) where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { self.0.get_ptrs(ptrs); self.1.get_ptrs(ptrs); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { (self.0.guard(), self.1.guard()) } } -unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>> Lockable<'a> for (A, B, C) { - type Guard = (A::Guard, B::Guard, C::Guard); +unsafe impl Lockable for (A, B, C) { + type Guard<'g> = (A::Guard<'g>, B::Guard<'g>, C::Guard<'g>) where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { self.0.get_ptrs(ptrs); self.1.get_ptrs(ptrs); self.2.get_ptrs(ptrs); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { (self.0.guard(), self.1.guard(), self.2.guard()) } } -unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<'a>> Lockable<'a> - for (A, B, C, D) -{ - type Guard = (A::Guard, B::Guard, C::Guard, D::Guard); +unsafe impl Lockable for (A, B, C, D) { + type Guard<'g> = (A::Guard<'g>, B::Guard<'g>, C::Guard<'g>, D::Guard<'g>) where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { self.0.get_ptrs(ptrs); self.1.get_ptrs(ptrs); self.2.get_ptrs(ptrs); self.3.get_ptrs(ptrs); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { ( self.0.guard(), self.1.guard(), @@ -235,12 +233,18 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<' } } -unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<'a>, E: Lockable<'a>> - Lockable<'a> for (A, B, C, D, E) +unsafe impl Lockable + for (A, B, C, D, E) { - type Guard = (A::Guard, B::Guard, C::Guard, D::Guard, E::Guard); - - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + type Guard<'g> = ( + A::Guard<'g>, + B::Guard<'g>, + C::Guard<'g>, + D::Guard<'g>, + E::Guard<'g>, + ) where Self: 'g; + + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { self.0.get_ptrs(ptrs); self.1.get_ptrs(ptrs); self.2.get_ptrs(ptrs); @@ -248,7 +252,7 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<' self.4.get_ptrs(ptrs); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { ( self.0.guard(), self.1.guard(), @@ -259,19 +263,19 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<' } } -unsafe impl< - 'a, - A: Lockable<'a>, - B: Lockable<'a>, - C: Lockable<'a>, - D: Lockable<'a>, - E: Lockable<'a>, - F: Lockable<'a>, - > Lockable<'a> for (A, B, C, D, E, F) +unsafe impl Lockable + for (A, B, C, D, E, F) { - type Guard = (A::Guard, B::Guard, C::Guard, D::Guard, E::Guard, F::Guard); - - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + type Guard<'g> = ( + A::Guard<'g>, + B::Guard<'g>, + C::Guard<'g>, + D::Guard<'g>, + E::Guard<'g>, + F::Guard<'g>, + ) where Self: 'g; + + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { self.0.get_ptrs(ptrs); self.1.get_ptrs(ptrs); self.2.get_ptrs(ptrs); @@ -280,7 +284,7 @@ unsafe impl< self.5.get_ptrs(ptrs); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { ( self.0.guard(), self.1.guard(), @@ -292,28 +296,20 @@ unsafe impl< } } -unsafe impl< - 'a, - A: Lockable<'a>, - B: Lockable<'a>, - C: Lockable<'a>, - D: Lockable<'a>, - E: Lockable<'a>, - F: Lockable<'a>, - G: Lockable<'a>, - > Lockable<'a> for (A, B, C, D, E, F, G) +unsafe impl + Lockable for (A, B, C, D, E, F, G) { - type Guard = ( - A::Guard, - B::Guard, - C::Guard, - D::Guard, - E::Guard, - F::Guard, - G::Guard, - ); - - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + type Guard<'g> = ( + A::Guard<'g>, + B::Guard<'g>, + C::Guard<'g>, + D::Guard<'g>, + E::Guard<'g>, + F::Guard<'g>, + G::Guard<'g>, + ) where Self: 'g; + + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { self.0.get_ptrs(ptrs); self.1.get_ptrs(ptrs); self.2.get_ptrs(ptrs); @@ -323,7 +319,7 @@ unsafe impl< self.6.get_ptrs(ptrs); } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { ( self.0.guard(), self.1.guard(), @@ -336,71 +332,63 @@ unsafe impl< } } -unsafe impl<'a, A: OwnedLockable<'a>> OwnedLockable<'a> for (A,) {} -unsafe impl<'a, A: OwnedLockable<'a>, B: OwnedLockable<'a>> OwnedLockable<'a> for (A, B) {} +unsafe impl OwnedLockable for (A,) {} +unsafe impl OwnedLockable for (A, B) {} -unsafe impl<'a, A: OwnedLockable<'a>, B: OwnedLockable<'a>, C: OwnedLockable<'a>> OwnedLockable<'a> - for (A, B, C) -{ -} +unsafe impl OwnedLockable for (A, B, C) {} -unsafe impl< - 'a, - A: OwnedLockable<'a>, - B: OwnedLockable<'a>, - C: OwnedLockable<'a>, - D: OwnedLockable<'a>, - > OwnedLockable<'a> for (A, B, C, D) +unsafe impl OwnedLockable + for (A, B, C, D) { } unsafe impl< 'a, - A: OwnedLockable<'a>, - B: OwnedLockable<'a>, - C: OwnedLockable<'a>, - D: OwnedLockable<'a>, - E: OwnedLockable<'a>, - > OwnedLockable<'a> for (A, B, C, D, E) + A: OwnedLockable, + B: OwnedLockable, + C: OwnedLockable, + D: OwnedLockable, + E: OwnedLockable, + > OwnedLockable for (A, B, C, D, E) { } unsafe impl< 'a, - A: OwnedLockable<'a>, - B: OwnedLockable<'a>, - C: OwnedLockable<'a>, - D: OwnedLockable<'a>, - E: OwnedLockable<'a>, - F: OwnedLockable<'a>, - > OwnedLockable<'a> for (A, B, C, D, E, F) + A: OwnedLockable, + B: OwnedLockable, + C: OwnedLockable, + D: OwnedLockable, + E: OwnedLockable, + F: OwnedLockable, + > OwnedLockable for (A, B, C, D, E, F) { } unsafe impl< 'a, - A: OwnedLockable<'a>, - B: OwnedLockable<'a>, - C: OwnedLockable<'a>, - D: OwnedLockable<'a>, - E: OwnedLockable<'a>, - F: OwnedLockable<'a>, - G: OwnedLockable<'a>, - > OwnedLockable<'a> for (A, B, C, D, E, F, G) + A: OwnedLockable, + B: OwnedLockable, + C: OwnedLockable, + D: OwnedLockable, + E: OwnedLockable, + F: OwnedLockable, + G: OwnedLockable, + > OwnedLockable for (A, B, C, D, E, F, G) { } -unsafe impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] { - type Guard = [T::Guard; N]; +unsafe impl Lockable for [T; N] { + type Guard<'g> = [T::Guard<'g>; N] where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { for lock in self { lock.get_ptrs(ptrs); } } - unsafe fn guard(&'a self) -> Self::Guard { - let mut guards = MaybeUninit::<[MaybeUninit; N]>::uninit().assume_init(); + unsafe fn guard<'g>(&'g self) -> Self::Guard<'g> { + let mut guards = MaybeUninit::<[MaybeUninit>; N]>::uninit().assume_init(); for i in 0..N { guards[i].write(self[i].guard()); } @@ -409,16 +397,16 @@ unsafe impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] { } } -unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Box<[T]> { - type Guard = Box<[T::Guard]>; +unsafe impl Lockable for Box<[T]> { + type Guard<'g> = Box<[T::Guard<'g>]> where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { for lock in self.iter() { lock.get_ptrs(ptrs); } } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { let mut guards = Vec::new(); for lock in self.iter() { guards.push(lock.guard()); @@ -428,16 +416,16 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Box<[T]> { } } -unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec { - type Guard = Vec; +unsafe impl Lockable for Vec { + type Guard<'g> = Vec> where Self: 'g; - fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { + fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { for lock in self { lock.get_ptrs(ptrs); } } - unsafe fn guard(&'a self) -> Self::Guard { + unsafe fn guard(&self) -> Self::Guard<'_> { let mut guards = Vec::new(); for lock in self { guards.push(lock.guard()); @@ -447,6 +435,6 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec { } } -unsafe impl<'a, T: OwnedLockable<'a>, const N: usize> OwnedLockable<'a> for [T; N] {} -unsafe impl<'a, T: OwnedLockable<'a>> OwnedLockable<'a> for Box<[T]> {} -unsafe impl<'a, T: OwnedLockable<'a>> OwnedLockable<'a> for Vec {} +unsafe impl OwnedLockable for [T; N] {} +unsafe impl OwnedLockable for Box<[T]> {} +unsafe impl OwnedLockable for Vec {} -- cgit v1.2.3 From cb28fb1ff3b5ea71c6fe11956015c7285cb3f3df Mon Sep 17 00:00:00 2001 From: Mica White Date: Tue, 21 May 2024 13:17:38 -0400 Subject: read-lock changes --- README.md | 6 +----- src/collection.rs | 2 +- src/lockable.rs | 4 ++-- src/rwlock.rs | 6 ++++-- src/rwlock/read_lock.rs | 16 ++++++++-------- src/rwlock/write_lock.rs | 16 ++++++++-------- 6 files changed, 24 insertions(+), 26 deletions(-) (limited to 'src/lockable.rs') diff --git a/README.md b/README.md index 51d8d67..66a4fc0 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,10 @@ println!("{}", *data.1); **Avoid `LockCollection::try_new`.** This constructor will check to make sure that the collection contains no duplicate locks. This is an O(n^2) operation, where n is the number of locks in the collection. `LockCollection::new` and `LockCollection::new_ref` don't need these checks because they use `OwnedLockable`, which is guaranteed to be unique as long as it is accessible. As a last resort, `LockCollection::new_unchecked` doesn't do this check, but is unsafe to call. -**Avoid using distinct lock orders for `LockCollection`.** The problem is that this library must iterate through the list of locks, and not complete until every single one of them is unlocked. This also means that attempting to lock multiple mutexes gives you a lower chance of ever running. Only one needs to be locked for the operation to need a reset. This problem can be prevented by not doing that in your code. Resources should be obtained in the same order on every thread. - -**Avoid tuples in `LockCollection`.** Tuples become spinlocks if the first value is already unlocked. This will be fixed in the future. For now, if you need a tuple, make the lock that is most likely to be locked the first element. +**Avoid using distinct lock orders for `RetryingLockCollection`.** The problem is that this collection must iterate through the list of locks, and not complete until every single one of them is unlocked. This also means that attempting to lock multiple mutexes gives you a lower chance of ever running. Only one needs to be locked for the operation to need a reset. This problem can be prevented by not doing that in your code. Resources should be obtained in the same order on every thread. ## Future Work -Although this library is able to successfully prevent deadlocks, livelocks may still be an issue. Imagine thread 1 gets resource 1, thread 2 gets resource 2, thread 1 realizes it can't get resource 2, thread 2 realizes it can't get resource 1, thread 1 drops resource 1, thread 2 drops resource 2, and then repeat forever. In practice, this situation probably wouldn't last forever. But it would be nice if this could be prevented somehow. A more fair system for getting sets of locks would help, but I have no clue what that looks like. - It might to possible to break the `ThreadKey` system by having two crates import this crate and call `ThreadKey::get`. I'm not quite sure how this works, but Rust could decide to give each crate their own key, ergo one thread would get two keys. I don't think the standard library would have this issue. At a certain point, I have to recognize that someone could also just import the standard library mutex and get a deadlock that way. We should add `Condvar` at some point. I didn't because I've never used it before, and I'm probably not the right person to solve this problem. I think all the synchronization problems could be solved by having `Condvar::wait` take a `ThreadKey` instead of a `MutexGuard`. Something similar can probably be done for `Barrier`. But again, I'm no expert. diff --git a/src/collection.rs b/src/collection.rs index d9c56d3..a11d60c 100644 --- a/src/collection.rs +++ b/src/collection.rs @@ -1,4 +1,4 @@ -use std::{marker::PhantomData}; +use std::marker::PhantomData; use crate::{ key::Keyable, diff --git a/src/lockable.rs b/src/lockable.rs index fe14e8c..a5646e1 100644 --- a/src/lockable.rs +++ b/src/lockable.rs @@ -124,7 +124,7 @@ unsafe impl OwnedLockable for Mutex {} unsafe impl OwnedLockable for RwLock {} -unsafe impl<'r, T: Send + 'r, R: RawRwLock + Send + Sync + 'r> Lockable for ReadLock<'r, T, R> { +unsafe impl Lockable for ReadLock { type Guard<'g> = RwLockReadRef<'g, T, R> where Self: 'g; fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { @@ -136,7 +136,7 @@ unsafe impl<'r, T: Send + 'r, R: RawRwLock + Send + Sync + 'r> Lockable for Read } } -unsafe impl<'r, T: Send + 'r, R: RawRwLock + Send + Sync + 'r> Lockable for WriteLock<'r, T, R> { +unsafe impl Lockable for WriteLock { type Guard<'g> = RwLockWriteRef<'g, T, R> where Self: 'g; fn get_ptrs<'a>(&'a self, ptrs: &mut Vec<&'a dyn Lock>) { diff --git a/src/rwlock.rs b/src/rwlock.rs index 7fb8c7a..40c5a6e 100644 --- a/src/rwlock.rs +++ b/src/rwlock.rs @@ -56,7 +56,8 @@ pub struct RwLock { /// that only read access is needed to the data. /// /// [`LockCollection`]: `crate::LockCollection` -pub struct ReadLock<'a, T: ?Sized, R>(&'a RwLock); +#[repr(transparent)] +pub struct ReadLock(RwLock); /// Grants write access to an [`RwLock`] /// @@ -64,7 +65,8 @@ pub struct ReadLock<'a, T: ?Sized, R>(&'a RwLock); /// that write access is needed to the data. /// /// [`LockCollection`]: `crate::LockCollection` -pub struct WriteLock<'a, T: ?Sized, R>(&'a RwLock); +#[repr(transparent)] +pub struct WriteLock(RwLock); /// RAII structure that unlocks the shared read access to a [`RwLock`] pub struct RwLockReadRef<'a, T: ?Sized, R: RawRwLock>( diff --git a/src/rwlock/read_lock.rs b/src/rwlock/read_lock.rs index 133ca7d..a8bb9be 100644 --- a/src/rwlock/read_lock.rs +++ b/src/rwlock/read_lock.rs @@ -6,7 +6,7 @@ use crate::key::Keyable; use super::{ReadLock, RwLock, RwLockReadGuard, RwLockReadRef}; -impl<'a, T: ?Sized + Debug, R: RawRwLock> Debug for ReadLock<'a, T, R> { +impl Debug for ReadLock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // safety: this is just a try lock, and the value is dropped // immediately after, so there's no risk of blocking ourselves @@ -28,19 +28,19 @@ impl<'a, T: ?Sized + Debug, R: RawRwLock> Debug for ReadLock<'a, T, R> { } } -impl<'a, T: ?Sized, R> From<&'a RwLock> for ReadLock<'a, T, R> { - fn from(value: &'a RwLock) -> Self { +impl From> for ReadLock { + fn from(value: RwLock) -> Self { Self::new(value) } } -impl<'a, T: ?Sized, R> AsRef> for ReadLock<'a, T, R> { +impl AsRef> for ReadLock { fn as_ref(&self) -> &RwLock { - self.0 + &self.0 } } -impl<'a, T: ?Sized, R> ReadLock<'a, T, R> { +impl ReadLock { /// Creates a new `ReadLock` which accesses the given [`RwLock`] /// /// # Examples @@ -52,12 +52,12 @@ impl<'a, T: ?Sized, R> ReadLock<'a, T, R> { /// let read_lock = ReadLock::new(&lock); /// ``` #[must_use] - pub const fn new(rwlock: &'a RwLock) -> Self { + pub const fn new(rwlock: RwLock) -> Self { Self(rwlock) } } -impl<'a, T: ?Sized, R: RawRwLock> ReadLock<'a, T, R> { +impl ReadLock { /// Locks the underlying [`RwLock`] with shared read access, blocking the /// current thread until it can be acquired. pub fn lock<'s, 'key: 's, Key: Keyable + 'key>( diff --git a/src/rwlock/write_lock.rs b/src/rwlock/write_lock.rs index c6b4c24..a344125 100644 --- a/src/rwlock/write_lock.rs +++ b/src/rwlock/write_lock.rs @@ -6,7 +6,7 @@ use crate::key::Keyable; use super::{RwLock, RwLockWriteGuard, RwLockWriteRef, WriteLock}; -impl<'a, T: ?Sized + Debug, R: RawRwLock> Debug for WriteLock<'a, T, R> { +impl Debug for WriteLock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // safety: this is just a try lock, and the value is dropped // immediately after, so there's no risk of blocking ourselves @@ -28,19 +28,19 @@ impl<'a, T: ?Sized + Debug, R: RawRwLock> Debug for WriteLock<'a, T, R> { } } -impl<'a, T: ?Sized, R> From<&'a RwLock> for WriteLock<'a, T, R> { - fn from(value: &'a RwLock) -> Self { +impl From> for WriteLock { + fn from(value: RwLock) -> Self { Self::new(value) } } -impl<'a, T: ?Sized, R> AsRef> for WriteLock<'a, T, R> { +impl AsRef> for WriteLock { fn as_ref(&self) -> &RwLock { - self.0 + &self.0 } } -impl<'a, T: ?Sized, R> WriteLock<'a, T, R> { +impl WriteLock { /// Creates a new `WriteLock` which accesses the given [`RwLock`] /// /// # Examples @@ -52,12 +52,12 @@ impl<'a, T: ?Sized, R> WriteLock<'a, T, R> { /// let write_lock = WriteLock::new(&lock); /// ``` #[must_use] - pub const fn new(rwlock: &'a RwLock) -> Self { + pub const fn new(rwlock: RwLock) -> Self { Self(rwlock) } } -impl<'a, T: ?Sized, R: RawRwLock> WriteLock<'a, T, R> { +impl WriteLock { /// Locks the underlying [`RwLock`] with exclusive write access, blocking /// the current until it can be acquired. pub fn lock<'s, 'key: 's, Key: Keyable + 'key>( -- cgit v1.2.3