summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/collection.rs104
-rw-r--r--src/guard.rs60
-rw-r--r--src/lib.rs4
-rw-r--r--src/lockable.rs252
-rw-r--r--src/rwlock.rs4
5 files changed, 207 insertions, 217 deletions
diff --git a/src/collection.rs b/src/collection.rs
new file mode 100644
index 0000000..809f340
--- /dev/null
+++ b/src/collection.rs
@@ -0,0 +1,104 @@
+use std::{
+ marker::PhantomData,
+ ops::{Deref, DerefMut},
+};
+
+use crate::{key::Keyable, lockable::Lockable};
+
+fn contains_duplicates(l: &[usize]) -> bool {
+ for i in 0..l.len() {
+ for j in 0..l.len() {
+ if i != j && l[i] == l[j] {
+ return true;
+ }
+ }
+ }
+
+ false
+}
+
+pub struct LockCollection<L> {
+ collection: L,
+}
+
+/// A guard for a generic [`Lockable`] type.
+pub struct LockGuard<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable + 'key> {
+ guard: L::Output,
+ key: Key,
+ _phantom: PhantomData<&'key ()>,
+}
+
+impl<L> LockCollection<L> {
+ /// Creates a new collections of locks.
+ ///
+ /// # Safety
+ ///
+ /// This results in undefined behavior if any locks are presented twice
+ /// within this collection.
+ pub const unsafe fn new_unchecked(collection: L) -> Self {
+ Self { collection }
+ }
+}
+
+impl<'a, L: Lockable<'a>> LockCollection<L> {
+ /// Creates a new collection of locks.
+ ///
+ /// This returns `None` if any locks are found twice in the given collection.
+ pub fn new(collection: L) -> Option<Self> {
+ let ptrs = collection.get_ptrs();
+ if contains_duplicates(&ptrs) {
+ return None;
+ }
+
+ Some(Self { collection })
+ }
+
+ /// Locks the lockable type and returns a guard that can be used to access
+ /// the underlying data.
+ pub fn lock<'key: 'a, Key: Keyable + 'key>(&'a self, key: Key) -> LockGuard<'a, 'key, L, Key> {
+ LockGuard {
+ // safety: we have the thread's key
+ guard: unsafe { self.collection.lock() },
+ key,
+ _phantom: PhantomData,
+ }
+ }
+
+ /// Attempts to lock the guard without blocking.
+ ///
+ /// If successful, this method returns a guard that can be used to access
+ /// the data. Otherwise, `None` is returned.
+ pub fn try_lock<'key: 'a, Key: Keyable + 'key>(
+ &'a self,
+ key: Key,
+ ) -> Option<LockGuard<'a, 'key, L, Key>> {
+ // safety: we have the thread's key
+ unsafe { self.collection.try_lock() }.map(|guard| LockGuard {
+ guard,
+ key,
+ _phantom: PhantomData,
+ })
+ }
+
+ /// Unlocks the underlying lockable data type, returning the key that's
+ /// associated with it.
+ #[allow(clippy::missing_const_for_fn)]
+ pub fn unlock<'key: 'a, Key: Keyable + 'key>(guard: LockGuard<'a, 'key, L, Key>) -> Key {
+ drop(guard.guard);
+ guard.key
+ }
+}
+
+impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> Deref for LockGuard<'a, 'key, L, Key> {
+ type Target = L::Output;
+
+ fn deref(&self) -> &Self::Target {
+ &self.guard
+ }
+}
+
+impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> DerefMut for LockGuard<'a, 'key, L, Key> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.guard
+ }
+}
diff --git a/src/guard.rs b/src/guard.rs
deleted file mode 100644
index 12021e2..0000000
--- a/src/guard.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use std::{
- marker::PhantomData,
- ops::{Deref, DerefMut},
-};
-
-use crate::{key::Keyable, lockable::Lockable};
-
-/// A guard for a generic [`Lockable`] type.
-pub struct LockGuard<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable + 'key> {
- guard: L::Output,
- key: Key,
- _phantom: PhantomData<&'key ()>,
-}
-
-impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> LockGuard<'a, 'key, L, Key> {
- /// Locks the lockable type and returns a guard that can be used to access
- /// the underlying data.
- pub fn lock(lock: &'a L, key: Key) -> Self {
- Self {
- // safety: we have the thread's key
- guard: unsafe { lock.lock() },
- key,
- _phantom: PhantomData,
- }
- }
-
- /// Attempts to lock the guard without blocking. If successful, this method
- /// returns a guard that can be used to access the data. Otherwise, the key
- /// is given back as an error.
- pub fn try_lock(lock: &'a L, key: Key) -> Option<Self> {
- // safety: we have the thread's key
- unsafe { lock.try_lock() }.map(|guard| Self {
- guard,
- key,
- _phantom: PhantomData,
- })
- }
-
- /// Unlocks the underlying lockable data type, returning the key that's
- /// associated with it.
- #[allow(clippy::missing_const_for_fn)]
- pub fn unlock(guard: Self) -> Key {
- L::unlock(guard.guard);
- guard.key
- }
-}
-
-impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> Deref for LockGuard<'a, 'key, L, Key> {
- type Target = L::Output;
-
- fn deref(&self) -> &Self::Target {
- &self.guard
- }
-}
-
-impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> DerefMut for LockGuard<'a, 'key, L, Key> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.guard
- }
-}
diff --git a/src/lib.rs b/src/lib.rs
index 3897615..25b6d03 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,14 +4,14 @@
#![allow(clippy::declare_interior_mutable_const)]
#![allow(clippy::semicolon_if_nothing_returned)]
-mod guard;
+mod collection;
mod key;
mod lockable;
pub mod mutex;
pub mod rwlock;
-pub use guard::LockGuard;
+pub use collection::LockCollection;
pub use key::{Key, ThreadKey};
pub use lockable::Lockable;
pub use mutex::SpinLock;
diff --git a/src/lockable.rs b/src/lockable.rs
index 050f856..ddcc1c8 100644
--- a/src/lockable.rs
+++ b/src/lockable.rs
@@ -34,11 +34,16 @@ mod sealed {
/// # Safety
///
/// A deadlock must never occur. The `unlock` method must correctly unlock the
-/// data.
+/// data. The `get_ptrs` method must be implemented correctly. The `Output`
+/// must be unlocked when it is dropped.
pub unsafe trait Lockable<'a>: sealed::Sealed {
/// The output of the lock
type Output;
+ /// Returns a list of all pointers to locks. This is used to ensure that
+ /// the same lock isn't included twice
+ fn get_ptrs(&self) -> Vec<usize>;
+
/// Blocks until the lock is acquired
///
/// # Safety
@@ -63,14 +68,15 @@ pub unsafe trait Lockable<'a>: sealed::Sealed {
///
/// [`ThreadKey`]: `crate::key::ThreadKey`
unsafe fn try_lock(&'a self) -> Option<Self::Output>;
-
- /// Release the lock
- fn unlock(guard: Self::Output);
}
unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &T {
type Output = T::Output;
+ fn get_ptrs(&self) -> Vec<usize> {
+ (*self).get_ptrs()
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
(*self).lock()
}
@@ -78,16 +84,15 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &T {
unsafe fn try_lock(&'a self) -> Option<Self::Output> {
(*self).try_lock()
}
-
- #[allow(clippy::semicolon_if_nothing_returned)]
- fn unlock(guard: Self::Output) {
- T::unlock(guard)
- }
}
unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &mut T {
type Output = T::Output;
+ fn get_ptrs(&self) -> Vec<usize> {
+ (**self).get_ptrs()
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
(**self).lock()
}
@@ -95,16 +100,15 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &mut T {
unsafe fn try_lock(&'a self) -> Option<Self::Output> {
(**self).try_lock()
}
-
- #[allow(clippy::semicolon_if_nothing_returned)]
- fn unlock(guard: Self::Output) {
- T::unlock(guard)
- }
}
unsafe impl<'a, T: 'a, R: RawMutex + 'a> Lockable<'a> for Mutex<T, R> {
type Output = MutexRef<'a, T, R>;
+ fn get_ptrs(&self) -> Vec<usize> {
+ vec![self as *const Self as usize]
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
self.lock_no_key()
}
@@ -112,15 +116,15 @@ unsafe impl<'a, T: 'a, R: RawMutex + 'a> Lockable<'a> for Mutex<T, R> {
unsafe fn try_lock(&'a self) -> Option<Self::Output> {
self.try_lock_no_key()
}
-
- fn unlock(guard: Self::Output) {
- drop(guard);
- }
}
unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for RwLock<T, R> {
type Output = RwLockWriteRef<'a, T, R>;
+ fn get_ptrs(&self) -> Vec<usize> {
+ vec![self as *const Self as usize]
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
self.write_no_key()
}
@@ -128,15 +132,15 @@ unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for RwLock<T, R> {
unsafe fn try_lock(&'a self) -> Option<Self::Output> {
self.try_write_no_key()
}
-
- fn unlock(guard: Self::Output) {
- drop(guard);
- }
}
unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for ReadLock<'a, T, R> {
type Output = RwLockReadRef<'a, T, R>;
+ fn get_ptrs(&self) -> Vec<usize> {
+ vec![self.0 as *const RwLock<T, R> as usize]
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
self.lock_no_key()
}
@@ -144,15 +148,15 @@ unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for ReadLock<'a, T, R> {
unsafe fn try_lock(&'a self) -> Option<Self::Output> {
self.try_lock_no_key()
}
-
- fn unlock(guard: Self::Output) {
- drop(guard);
- }
}
unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for WriteLock<'a, T, R> {
type Output = RwLockWriteRef<'a, T, R>;
+ fn get_ptrs(&self) -> Vec<usize> {
+ vec![self.0 as *const RwLock<T, R> as usize]
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
self.lock_no_key()
}
@@ -160,15 +164,17 @@ unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for WriteLock<'a, T, R> {
unsafe fn try_lock(&'a self) -> Option<Self::Output> {
self.try_lock_no_key()
}
-
- fn unlock(guard: Self::Output) {
- drop(guard);
- }
}
unsafe impl<'a, A: Lockable<'a>> Lockable<'a> for (A,) {
type Output = (A::Output,);
+ fn get_ptrs(&self) -> Vec<usize> {
+ let mut ptrs = Vec::with_capacity(1);
+ ptrs.append(&mut self.0.get_ptrs());
+ ptrs
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
(self.0.lock(),)
}
@@ -176,20 +182,22 @@ unsafe impl<'a, A: Lockable<'a>> Lockable<'a> for (A,) {
unsafe fn try_lock(&'a self) -> Option<Self::Output> {
self.0.try_lock().map(|a| (a,))
}
-
- fn unlock(guard: Self::Output) {
- A::unlock(guard.0);
- }
}
unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>> Lockable<'a> for (A, B) {
type Output = (A::Output, B::Output);
+ fn get_ptrs(&self) -> Vec<usize> {
+ let mut ptrs = Vec::with_capacity(2);
+ ptrs.append(&mut self.0.get_ptrs());
+ ptrs.append(&mut self.1.get_ptrs());
+ ptrs
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
loop {
let lock0 = self.0.lock();
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
continue;
};
@@ -202,32 +210,31 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>> Lockable<'a> for (A, B) {
return None;
};
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
return None;
};
Some((lock0, lock1))
}
-
- fn unlock(guard: Self::Output) {
- A::unlock(guard.0);
- B::unlock(guard.1);
- }
}
unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>> Lockable<'a> for (A, B, C) {
type Output = (A::Output, B::Output, C::Output);
+ fn get_ptrs(&self) -> Vec<usize> {
+ let mut ptrs = Vec::with_capacity(3);
+ ptrs.append(&mut self.0.get_ptrs());
+ ptrs.append(&mut self.1.get_ptrs());
+ ptrs.append(&mut self.2.get_ptrs());
+ ptrs
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
loop {
let lock0 = self.0.lock();
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
continue;
};
let Some(lock2) = self.2.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
continue;
};
@@ -240,23 +247,14 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>> Lockable<'a>
return None;
};
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
return None;
};
let Some(lock2) = self.2.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
return None;
};
Some((lock0, lock1, lock2))
}
-
- fn unlock(guard: Self::Output) {
- A::unlock(guard.0);
- B::unlock(guard.1);
- C::unlock(guard.2);
- }
}
unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<'a>> Lockable<'a>
@@ -264,22 +262,25 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<'
{
type Output = (A::Output, B::Output, C::Output, D::Output);
+ fn get_ptrs(&self) -> Vec<usize> {
+ let mut ptrs = Vec::with_capacity(4);
+ ptrs.append(&mut self.0.get_ptrs());
+ ptrs.append(&mut self.1.get_ptrs());
+ ptrs.append(&mut self.2.get_ptrs());
+ ptrs.append(&mut self.3.get_ptrs());
+ ptrs
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
loop {
let lock0 = self.0.lock();
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
continue;
};
let Some(lock2) = self.2.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
continue;
};
let Some(lock3) = self.3.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
continue;
};
@@ -292,30 +293,17 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<'
return None;
};
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
return None;
};
let Some(lock2) = self.2.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
return None;
};
let Some(lock3) = self.3.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
return None;
};
Some((lock0, lock1, lock2, lock3))
}
-
- fn unlock(guard: Self::Output) {
- A::unlock(guard.0);
- B::unlock(guard.1);
- C::unlock(guard.2);
- D::unlock(guard.3);
- }
}
unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<'a>, E: Lockable<'a>>
@@ -323,29 +311,29 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<'
{
type Output = (A::Output, B::Output, C::Output, D::Output, E::Output);
+ fn get_ptrs(&self) -> Vec<usize> {
+ let mut ptrs = Vec::with_capacity(5);
+ ptrs.append(&mut self.0.get_ptrs());
+ ptrs.append(&mut self.1.get_ptrs());
+ ptrs.append(&mut self.2.get_ptrs());
+ ptrs.append(&mut self.3.get_ptrs());
+ ptrs.append(&mut self.4.get_ptrs());
+ ptrs
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
loop {
let lock0 = self.0.lock();
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
continue;
};
let Some(lock2) = self.2.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
continue;
};
let Some(lock3) = self.3.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
continue;
};
let Some(lock4) = self.4.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
- D::unlock(lock3);
continue;
};
@@ -358,38 +346,20 @@ unsafe impl<'a, A: Lockable<'a>, B: Lockable<'a>, C: Lockable<'a>, D: Lockable<'
return None;
};
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
return None;
};
let Some(lock2) = self.2.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
return None;
};
let Some(lock3) = self.3.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
return None;
};
let Some(lock4) = self.4.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
- D::unlock(lock3);
return None;
};
Some((lock0, lock1, lock2, lock3, lock4))
}
-
- fn unlock(guard: Self::Output) {
- A::unlock(guard.0);
- B::unlock(guard.1);
- C::unlock(guard.2);
- D::unlock(guard.3);
- E::unlock(guard.4);
- }
}
unsafe impl<
@@ -411,37 +381,33 @@ unsafe impl<
F::Output,
);
+ fn get_ptrs(&self) -> Vec<usize> {
+ let mut ptrs = Vec::with_capacity(6);
+ ptrs.append(&mut self.0.get_ptrs());
+ ptrs.append(&mut self.1.get_ptrs());
+ ptrs.append(&mut self.2.get_ptrs());
+ ptrs.append(&mut self.3.get_ptrs());
+ ptrs.append(&mut self.4.get_ptrs());
+ ptrs.append(&mut self.5.get_ptrs());
+ ptrs
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
loop {
let lock0 = self.0.lock();
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
continue;
};
let Some(lock2) = self.2.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
continue;
};
let Some(lock3) = self.3.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
continue;
};
let Some(lock4) = self.4.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
- D::unlock(lock3);
continue;
};
let Some(lock5) = self.5.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
- D::unlock(lock3);
- E::unlock(lock4);
continue;
};
@@ -454,52 +420,36 @@ unsafe impl<
return None;
};
let Some(lock1) = self.1.try_lock() else {
- A::unlock(lock0);
return None;
};
let Some(lock2) = self.2.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
return None;
};
let Some(lock3) = self.3.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
return None;
};
let Some(lock4) = self.4.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
- D::unlock(lock3);
return None;
};
let Some(lock5) = self.5.try_lock() else {
- A::unlock(lock0);
- B::unlock(lock1);
- C::unlock(lock2);
- D::unlock(lock3);
- E::unlock(lock4);
return None;
};
Some((lock0, lock1, lock2, lock3, lock4, lock5))
}
-
- fn unlock(guard: Self::Output) {
- A::unlock(guard.0);
- B::unlock(guard.1);
- C::unlock(guard.2);
- D::unlock(guard.3);
- E::unlock(guard.4);
- F::unlock(guard.5);
- }
}
unsafe impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] {
type Output = [T::Output; N];
+ fn get_ptrs(&self) -> Vec<usize> {
+ let mut ptrs = Vec::with_capacity(N);
+ for lock in self {
+ ptrs.append(&mut lock.get_ptrs());
+ }
+ ptrs
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
unsafe fn unlock_partial<'a, T: Lockable<'a>, const N: usize>(
guards: [MaybeUninit<T::Output>; N],
@@ -509,7 +459,7 @@ unsafe impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] {
if i == upto {
break;
}
- T::unlock(guard.assume_init());
+ drop(guard.assume_init());
}
}
@@ -542,7 +492,7 @@ unsafe impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] {
if i == upto {
break;
}
- T::unlock(guard.assume_init());
+ drop(guard.assume_init());
}
}
@@ -558,15 +508,19 @@ unsafe impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] {
Some(outputs.map(|mu| mu.assume_init()))
}
-
- fn unlock(guard: Self::Output) {
- guard.map(T::unlock);
- }
}
unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec<T> {
type Output = Vec<T::Output>;
+ fn get_ptrs(&self) -> Vec<usize> {
+ let mut ptrs = Vec::with_capacity(self.len());
+ for lock in self {
+ ptrs.append(&mut lock.get_ptrs());
+ }
+ ptrs
+ }
+
unsafe fn lock(&'a self) -> Self::Output {
'outer: loop {
let mut outputs = Vec::with_capacity(self.len());
@@ -579,7 +533,6 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec<T> {
if let Some(guard) = lock.try_lock() {
outputs.push(guard);
} else {
- Self::unlock(outputs);
continue 'outer;
};
}
@@ -594,17 +547,10 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec<T> {
if let Some(guard) = lock.try_lock() {
outputs.push(guard);
} else {
- Self::unlock(outputs);
return None;
};
}
Some(outputs)
}
-
- fn unlock(guard: Self::Output) {
- for guard in guard {
- T::unlock(guard);
- }
- }
}
diff --git a/src/rwlock.rs b/src/rwlock.rs
index 16ad3c3..722ca2f 100644
--- a/src/rwlock.rs
+++ b/src/rwlock.rs
@@ -17,9 +17,9 @@ pub struct RwLock<T: ?Sized, R> {
value: UnsafeCell<T>,
}
-pub struct ReadLock<'a, T: ?Sized, R>(&'a RwLock<T, R>);
+pub struct ReadLock<'a, T: ?Sized, R>(pub(crate) &'a RwLock<T, R>);
-pub struct WriteLock<'a, T: ?Sized, R>(&'a RwLock<T, R>);
+pub struct WriteLock<'a, T: ?Sized, R>(pub(crate) &'a RwLock<T, R>);
pub struct RwLockReadRef<'a, T: ?Sized, R: RawRwLock>(&'a RwLock<T, R>);