summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/collection.rs2
-rw-r--r--src/collection/boxed.rs46
-rw-r--r--src/collection/guard.rs2
-rw-r--r--src/collection/owned.rs41
-rw-r--r--src/collection/ref.rs32
-rw-r--r--src/collection/retry.rs268
-rw-r--r--src/collection/utils.rs8
-rw-r--r--src/lockable.rs170
-rw-r--r--src/mutex.rs2
-rw-r--r--src/mutex/guard.rs3
-rw-r--r--src/mutex/mutex.rs119
-rw-r--r--src/poisonable.rs2
-rw-r--r--src/poisonable/flag.rs4
-rw-r--r--src/poisonable/guard.rs3
-rw-r--r--src/poisonable/poisonable.rs36
-rw-r--r--src/rwlock.rs2
-rw-r--r--src/rwlock/read_guard.rs3
-rw-r--r--src/rwlock/rwlock.rs131
-rw-r--r--src/rwlock/write_guard.rs3
19 files changed, 421 insertions, 456 deletions
diff --git a/src/collection.rs b/src/collection.rs
index a8ae0b7..db68382 100644
--- a/src/collection.rs
+++ b/src/collection.rs
@@ -1,5 +1,5 @@
use std::cell::UnsafeCell;
-use std::marker::{PhantomData, PhantomPinned};
+use std::marker::PhantomData;
use crate::{key::Keyable, lockable::RawLock};
diff --git a/src/collection/boxed.rs b/src/collection/boxed.rs
index c359098..bef3df2 100644
--- a/src/collection/boxed.rs
+++ b/src/collection/boxed.rs
@@ -21,43 +21,55 @@ fn contains_duplicates(l: &[&dyn RawLock]) -> bool {
}
unsafe impl<L: Lockable + Send + Sync> RawLock for BoxedLockCollection<L> {
- unsafe fn lock(&self) {
+ fn kill(&self) {
+ for lock in &self.locks {
+ lock.kill();
+ }
+ }
+
+ unsafe fn raw_lock(&self) {
for lock in self.locks() {
- lock.lock();
+ lock.raw_lock();
}
}
- unsafe fn try_lock(&self) -> bool {
+ unsafe fn raw_try_lock(&self) -> bool {
utils::ordered_try_lock(self.locks())
}
- unsafe fn unlock(&self) {
+ unsafe fn raw_unlock(&self) {
for lock in self.locks() {
- lock.unlock();
+ lock.raw_unlock();
}
}
- unsafe fn read(&self) {
+ unsafe fn raw_read(&self) {
for lock in self.locks() {
- lock.read();
+ lock.raw_read();
}
}
- unsafe fn try_read(&self) -> bool {
+ unsafe fn raw_try_read(&self) -> bool {
utils::ordered_try_read(self.locks())
}
- unsafe fn unlock_read(&self) {
+ unsafe fn raw_unlock_read(&self) {
for lock in self.locks() {
- lock.unlock_read();
+ lock.raw_unlock_read();
}
}
}
unsafe impl<L: Lockable> Lockable for BoxedLockCollection<L> {
- type Guard<'g> = L::Guard<'g> where Self: 'g;
+ type Guard<'g>
+ = L::Guard<'g>
+ where
+ Self: 'g;
- type ReadGuard<'g> = L::ReadGuard<'g> 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())
@@ -109,6 +121,8 @@ impl<L: OwnedLockable, I: FromIterator<L> + OwnedLockable> FromIterator<L>
}
}
+// safety: the RawLocks must be send because they come from the Send Lockable
+#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl<L: Send> Send for BoxedLockCollection<L> {}
unsafe impl<L: Sync> Sync for BoxedLockCollection<L> {}
@@ -261,11 +275,11 @@ impl<L: Lockable> BoxedLockCollection<L> {
data_ref.get_ptrs(&mut locks);
// cast to *const () because fat pointers can't be converted to usize
- locks.sort_by_key(|lock| (*lock as *const dyn RawLock).cast::<()>() as usize);
+ locks.sort_by_key(|lock| (&raw const **lock).cast::<()>() as usize);
// safety we're just changing the lifetimes
let locks: Vec<&'static dyn RawLock> = std::mem::transmute(locks);
- let data = data as *const UnsafeCell<L>;
+ let data = &raw const *data;
Self { data, locks }
}
@@ -323,7 +337,7 @@ impl<L: Lockable> BoxedLockCollection<L> {
) -> LockGuard<'key, L::Guard<'g>, Key> {
for lock in self.locks() {
// safety: we have the thread key
- unsafe { lock.lock() };
+ unsafe { lock.raw_lock() };
}
LockGuard {
@@ -427,7 +441,7 @@ impl<L: Sharable> BoxedLockCollection<L> {
) -> LockGuard<'key, L::ReadGuard<'g>, Key> {
for lock in self.locks() {
// safety: we have the thread key
- unsafe { lock.read() };
+ unsafe { lock.raw_read() };
}
LockGuard {
diff --git a/src/collection/guard.rs b/src/collection/guard.rs
index 70bb3a6..d604680 100644
--- a/src/collection/guard.rs
+++ b/src/collection/guard.rs
@@ -48,8 +48,6 @@ mod tests {
use crate::collection::OwnedLockCollection;
use crate::{RwLock, ThreadKey};
- use super::*;
-
#[test]
fn guard_display_works() {
let key = ThreadKey::get().unwrap();
diff --git a/src/collection/owned.rs b/src/collection/owned.rs
index 9aa7460..69347cc 100644
--- a/src/collection/owned.rs
+++ b/src/collection/owned.rs
@@ -12,49 +12,62 @@ fn get_locks<L: Lockable>(data: &L) -> Vec<&dyn RawLock> {
}
unsafe impl<L: Lockable + Send + Sync> RawLock for OwnedLockCollection<L> {
- unsafe fn lock(&self) {
+ fn kill(&self) {
let locks = get_locks(&self.data);
for lock in locks {
- lock.lock();
+ lock.kill();
}
}
- unsafe fn try_lock(&self) -> bool {
+ unsafe fn raw_lock(&self) {
+ let locks = get_locks(&self.data);
+ for lock in locks {
+ lock.raw_lock();
+ }
+ }
+
+ unsafe fn raw_try_lock(&self) -> bool {
let locks = get_locks(&self.data);
utils::ordered_try_lock(&locks)
}
- unsafe fn unlock(&self) {
+ unsafe fn raw_unlock(&self) {
let locks = get_locks(&self.data);
for lock in locks {
- lock.unlock();
+ lock.raw_unlock();
}
}
- unsafe fn read(&self) {
+ unsafe fn raw_read(&self) {
let locks = get_locks(&self.data);
for lock in locks {
- lock.read();
+ lock.raw_read();
}
}
- unsafe fn try_read(&self) -> bool {
+ unsafe fn raw_try_read(&self) -> bool {
let locks = get_locks(&self.data);
utils::ordered_try_read(&locks)
}
- unsafe fn unlock_read(&self) {
+ unsafe fn raw_unlock_read(&self) {
let locks = get_locks(&self.data);
for lock in locks {
- lock.unlock_read();
+ lock.raw_unlock_read();
}
}
}
unsafe impl<L: Lockable> Lockable for OwnedLockCollection<L> {
- type Guard<'g> = L::Guard<'g> where Self: 'g;
+ type Guard<'g>
+ = L::Guard<'g>
+ where
+ Self: 'g;
- type ReadGuard<'g> = L::ReadGuard<'g> 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)
@@ -196,7 +209,7 @@ impl<L: OwnedLockable> OwnedLockCollection<L> {
for lock in locks {
// safety: we have the thread key, and these locks happen in a
// predetermined order
- unsafe { lock.lock() };
+ unsafe { lock.raw_lock() };
}
// safety: we've locked all of this already
@@ -310,7 +323,7 @@ impl<L: Sharable> OwnedLockCollection<L> {
for lock in locks {
// safety: we have the thread key, and these locks happen in a
// predetermined order
- unsafe { lock.read() };
+ unsafe { lock.raw_read() };
}
// safety: we've locked all of this already
diff --git a/src/collection/ref.rs b/src/collection/ref.rs
index 7c0d40a..0e2f057 100644
--- a/src/collection/ref.rs
+++ b/src/collection/ref.rs
@@ -10,7 +10,7 @@ use super::{utils, LockGuard, RefLockCollection};
pub fn get_locks<L: Lockable>(data: &L) -> Vec<&dyn RawLock> {
let mut locks = Vec::new();
data.get_ptrs(&mut locks);
- locks.sort_by_key(|lock| *lock as *const dyn RawLock);
+ locks.sort_by_key(|lock| &raw const **lock);
locks
}
@@ -45,35 +45,41 @@ where
}
unsafe impl<L: Lockable + Send + Sync> RawLock for RefLockCollection<'_, L> {
- unsafe fn lock(&self) {
+ fn kill(&self) {
for lock in &self.locks {
- lock.lock();
+ lock.kill();
}
}
- unsafe fn try_lock(&self) -> bool {
+ unsafe fn raw_lock(&self) {
+ for lock in &self.locks {
+ lock.raw_lock();
+ }
+ }
+
+ unsafe fn raw_try_lock(&self) -> bool {
utils::ordered_try_lock(&self.locks)
}
- unsafe fn unlock(&self) {
+ unsafe fn raw_unlock(&self) {
for lock in &self.locks {
- lock.unlock();
+ lock.raw_unlock();
}
}
- unsafe fn read(&self) {
+ unsafe fn raw_read(&self) {
for lock in &self.locks {
- lock.read();
+ lock.raw_read();
}
}
- unsafe fn try_read(&self) -> bool {
+ unsafe fn raw_try_read(&self) -> bool {
utils::ordered_try_read(&self.locks)
}
- unsafe fn unlock_read(&self) {
+ unsafe fn raw_unlock_read(&self) {
for lock in &self.locks {
- lock.unlock_read();
+ lock.raw_unlock_read();
}
}
}
@@ -225,7 +231,7 @@ impl<'a, L: Lockable> RefLockCollection<'a, L> {
) -> LockGuard<'key, L::Guard<'a>, Key> {
for lock in &self.locks {
// safety: we have the thread key
- unsafe { lock.lock() };
+ unsafe { lock.raw_lock() };
}
LockGuard {
@@ -333,7 +339,7 @@ impl<'a, L: Sharable> RefLockCollection<'a, L> {
) -> LockGuard<'key, L::ReadGuard<'a>, Key> {
for lock in &self.locks {
// safety: we have the thread key
- unsafe { lock.read() };
+ unsafe { lock.raw_read() };
}
LockGuard {
diff --git a/src/collection/retry.rs b/src/collection/retry.rs
index 8a10fc3..05adc3e 100644
--- a/src/collection/retry.rs
+++ b/src/collection/retry.rs
@@ -8,11 +8,18 @@ use std::marker::PhantomData;
use super::{LockGuard, RetryingLockCollection};
+/// Get all raw locks in the collection
+fn get_locks<L: Lockable>(data: &L) -> Vec<&dyn RawLock> {
+ let mut locks = Vec::new();
+ data.get_ptrs(&mut locks);
+ locks
+}
+
/// Checks that a collection contains no duplicate references to a lock.
fn contains_duplicates<L: Lockable>(data: L) -> bool {
let mut locks = Vec::new();
data.get_ptrs(&mut locks);
- let locks = locks.into_iter().map(|l| l as *const dyn RawLock);
+ let locks = locks.into_iter().map(|l| &raw const *l);
let mut locks_set = HashSet::with_capacity(locks.len());
for lock in locks {
@@ -24,11 +31,17 @@ fn contains_duplicates<L: Lockable>(data: L) -> bool {
false
}
-unsafe impl<L: Lockable + Send + Sync> RawLock for RetryingLockCollection<L> {
- unsafe fn lock(&self) {
+unsafe impl<L: Lockable> RawLock for RetryingLockCollection<L> {
+ fn kill(&self) {
+ let locks = get_locks(&self.data);
+ for lock in locks {
+ lock.kill();
+ }
+ }
+
+ unsafe fn raw_lock(&self) {
let mut first_index = 0;
- let mut locks = Vec::new();
- self.data.get_ptrs(&mut locks);
+ let locks = get_locks(&self.data);
if locks.is_empty() {
return;
@@ -37,23 +50,27 @@ unsafe impl<L: Lockable + Send + Sync> RawLock for RetryingLockCollection<L> {
unsafe {
'outer: loop {
// safety: we have the thread key
- locks[first_index].lock();
+ locks[first_index].raw_lock();
for (i, lock) in locks.iter().enumerate() {
if i == first_index {
continue;
}
+ // If the lock has been killed, then this returns false
+ // instead of panicking. This sounds like a problem, but if
+ // it does return false, then the lock function is called
+ // immediately after, causing a panic
// safety: we have the thread key
- if !lock.try_lock() {
+ if !lock.raw_try_lock() {
for lock in locks.iter().take(i) {
// safety: we already locked all of these
- lock.unlock();
+ lock.raw_unlock();
}
if first_index >= i {
// safety: this is already locked and can't be unlocked
// by the previous loop
- locks[first_index].unlock();
+ locks[first_index].raw_unlock();
}
first_index = i;
@@ -67,9 +84,8 @@ unsafe impl<L: Lockable + Send + Sync> RawLock for RetryingLockCollection<L> {
};
}
- unsafe fn try_lock(&self) -> bool {
- let mut locks = Vec::new();
- self.data.get_ptrs(&mut locks);
+ unsafe fn raw_try_lock(&self) -> bool {
+ let locks = get_locks(&self.data);
if locks.is_empty() {
return true;
@@ -78,10 +94,10 @@ unsafe impl<L: Lockable + Send + Sync> RawLock for RetryingLockCollection<L> {
unsafe {
for (i, lock) in locks.iter().enumerate() {
// safety: we have the thread key
- if !lock.try_lock() {
+ if !lock.raw_try_lock() {
for lock in locks.iter().take(i) {
// safety: we already locked all of these
- lock.unlock();
+ lock.raw_unlock();
}
return false;
}
@@ -91,39 +107,37 @@ unsafe impl<L: Lockable + Send + Sync> RawLock for RetryingLockCollection<L> {
true
}
- unsafe fn unlock(&self) {
- let mut locks = Vec::new();
- self.get_ptrs(&mut locks);
+ unsafe fn raw_unlock(&self) {
+ let locks = get_locks(&self.data);
for lock in locks {
- lock.unlock();
+ lock.raw_unlock();
}
}
- unsafe fn read(&self) {
+ unsafe fn raw_read(&self) {
let mut first_index = 0;
- let mut locks = Vec::new();
- self.data.get_ptrs(&mut locks);
+ let locks = get_locks(&self.data);
'outer: loop {
// safety: we have the thread key
- locks[first_index].read();
+ locks[first_index].raw_read();
for (i, lock) in locks.iter().enumerate() {
if i == first_index {
continue;
}
// safety: we have the thread key
- if !lock.try_read() {
+ if !lock.raw_try_read() {
for lock in locks.iter().take(i) {
// safety: we already locked all of these
- lock.unlock_read();
+ lock.raw_unlock_read();
}
if first_index >= i {
// safety: this is already locked and can't be unlocked
// by the previous loop
- locks[first_index].unlock_read();
+ locks[first_index].raw_unlock_read();
}
first_index = i;
@@ -133,9 +147,8 @@ unsafe impl<L: Lockable + Send + Sync> RawLock for RetryingLockCollection<L> {
}
}
- unsafe fn try_read(&self) -> bool {
- let mut locks = Vec::new();
- self.data.get_ptrs(&mut locks);
+ unsafe fn raw_try_read(&self) -> bool {
+ let locks = get_locks(&self.data);
if locks.is_empty() {
return true;
@@ -144,10 +157,10 @@ unsafe impl<L: Lockable + Send + Sync> RawLock for RetryingLockCollection<L> {
unsafe {
for (i, lock) in locks.iter().enumerate() {
// safety: we have the thread key
- if !lock.try_read() {
+ if !lock.raw_try_read() {
for lock in locks.iter().take(i) {
// safety: we already locked all of these
- lock.unlock_read();
+ lock.raw_unlock_read();
}
return false;
}
@@ -157,20 +170,25 @@ unsafe impl<L: Lockable + Send + Sync> RawLock for RetryingLockCollection<L> {
true
}
- unsafe fn unlock_read(&self) {
- let mut locks = Vec::new();
- self.get_ptrs(&mut locks);
+ unsafe fn raw_unlock_read(&self) {
+ let locks = get_locks(&self.data);
for lock in locks {
- lock.unlock_read();
+ lock.raw_unlock_read();
}
}
}
unsafe impl<L: Lockable> Lockable for RetryingLockCollection<L> {
- type Guard<'g> = L::Guard<'g> where Self: 'g;
+ type Guard<'g>
+ = L::Guard<'g>
+ where
+ Self: 'g;
- type ReadGuard<'g> = L::ReadGuard<'g> 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)
@@ -186,7 +204,8 @@ unsafe impl<L: Lockable> Lockable for RetryingLockCollection<L> {
}
impl<L: LockableAsMut> LockableAsMut for RetryingLockCollection<L> {
- type Inner<'a> = L::Inner<'a>
+ type Inner<'a>
+ = L::Inner<'a>
where
Self: 'a;
@@ -419,55 +438,16 @@ impl<L: Lockable> RetryingLockCollection<L> {
&'g self,
key: Key,
) -> LockGuard<'key, L::Guard<'g>, Key> {
- let mut first_index = 0;
- let mut locks = Vec::new();
- self.data.get_ptrs(&mut locks);
+ unsafe {
+ // safety: we're taking the thread key
+ self.raw_lock();
- if locks.is_empty() {
- return LockGuard {
- // safety: there's no data being returned
- guard: unsafe { self.data.guard() },
+ LockGuard {
+ // safety: we just locked the collection
+ guard: self.guard(),
key,
_phantom: PhantomData,
- };
- }
-
- let guard = unsafe {
- 'outer: loop {
- // safety: we have the thread key
- locks[first_index].lock();
- for (i, lock) in locks.iter().enumerate() {
- if i == first_index {
- continue;
- }
-
- // safety: we have the thread key
- if !lock.try_lock() {
- for lock in locks.iter().take(i) {
- // safety: we already locked all of these
- lock.unlock();
- }
-
- if first_index >= i {
- // safety: this is already locked and can't be unlocked
- // by the previous loop
- locks[first_index].unlock();
- }
-
- first_index = i;
- continue 'outer;
- }
- }
-
- // safety: we locked all the data
- break self.data.guard();
}
- };
-
- LockGuard {
- guard,
- key,
- _phantom: PhantomData,
}
}
@@ -500,39 +480,15 @@ impl<L: Lockable> RetryingLockCollection<L> {
&'g self,
key: Key,
) -> Option<LockGuard<'key, L::Guard<'g>, Key>> {
- let mut locks = Vec::new();
- self.data.get_ptrs(&mut locks);
-
- if locks.is_empty() {
- return Some(LockGuard {
- // safety: there's no data being returned
- guard: unsafe { self.data.guard() },
+ unsafe {
+ // safety: we're taking the thread key
+ self.raw_try_lock().then(|| LockGuard {
+ // safety: we just succeeded in locking everything
+ guard: self.guard(),
key,
_phantom: PhantomData,
- });
+ })
}
-
- let guard = unsafe {
- for (i, lock) in locks.iter().enumerate() {
- // safety: we have the thread key
- if !lock.try_lock() {
- for lock in locks.iter().take(i) {
- // safety: we already locked all of these
- lock.unlock();
- }
- return None;
- }
- }
-
- // safety: we locked all the data
- self.data.guard()
- };
-
- Some(LockGuard {
- guard,
- key,
- _phantom: PhantomData,
- })
}
/// Unlocks the underlying lockable data type, returning the key that's
@@ -584,55 +540,16 @@ impl<L: Sharable> RetryingLockCollection<L> {
&'g self,
key: Key,
) -> LockGuard<'key, L::ReadGuard<'g>, Key> {
- let mut first_index = 0;
- let mut locks = Vec::new();
- self.data.get_ptrs(&mut locks);
+ unsafe {
+ // safety: we're taking the thread key
+ self.raw_read();
- if locks.is_empty() {
- return LockGuard {
- // safety: there's no data being returned
- guard: unsafe { self.data.read_guard() },
+ LockGuard {
+ // safety: we just locked the collection
+ guard: self.read_guard(),
key,
_phantom: PhantomData,
- };
- }
-
- let guard = unsafe {
- 'outer: loop {
- // safety: we have the thread key
- locks[first_index].read();
- for (i, lock) in locks.iter().enumerate() {
- if i == first_index {
- continue;
- }
-
- // safety: we have the thread key
- if !lock.try_read() {
- for lock in locks.iter().take(i) {
- // safety: we already locked all of these
- lock.unlock_read();
- }
-
- if first_index >= i {
- // safety: this is already locked and can't be unlocked
- // by the previous loop
- locks[first_index].unlock_read();
- }
-
- first_index = i;
- continue 'outer;
- }
- }
-
- // safety: we locked all the data
- break self.data.read_guard();
}
- };
-
- LockGuard {
- guard,
- key,
- _phantom: PhantomData,
}
}
@@ -666,39 +583,15 @@ impl<L: Sharable> RetryingLockCollection<L> {
&'g self,
key: Key,
) -> Option<LockGuard<'key, L::ReadGuard<'g>, Key>> {
- let mut locks = Vec::new();
- self.data.get_ptrs(&mut locks);
-
- if locks.is_empty() {
- return Some(LockGuard {
- // safety: there's no data being returned
- guard: unsafe { self.data.read_guard() },
+ unsafe {
+ // safety: we're taking the thread key
+ self.raw_try_lock().then(|| LockGuard {
+ // safety: we just succeeded in locking everything
+ guard: self.read_guard(),
key,
_phantom: PhantomData,
- });
+ })
}
-
- let guard = unsafe {
- for (i, lock) in locks.iter().enumerate() {
- // safety: we have the thread key
- if !lock.try_read() {
- for lock in locks.iter().take(i) {
- // safety: we already locked all of these
- lock.unlock_read();
- }
- return None;
- }
- }
-
- // safety: we locked all the data
- self.data.read_guard()
- };
-
- Some(LockGuard {
- guard,
- key,
- _phantom: PhantomData,
- })
}
/// Unlocks the underlying lockable data type, returning the key that's
@@ -786,7 +679,6 @@ mod tests {
use super::*;
use crate::collection::BoxedLockCollection;
use crate::{Mutex, RwLock, ThreadKey};
- use lock_api::{RawMutex, RawRwLock};
#[test]
fn nonduplicate_lock_references_are_allowed() {
diff --git a/src/collection/utils.rs b/src/collection/utils.rs
index 8177c1d..c114541 100644
--- a/src/collection/utils.rs
+++ b/src/collection/utils.rs
@@ -7,12 +7,12 @@ pub unsafe fn ordered_try_lock(locks: &[&dyn RawLock]) -> bool {
unsafe {
for (i, lock) in locks.iter().enumerate() {
// safety: we have the thread key
- let success = lock.try_lock();
+ let success = lock.raw_try_lock();
if !success {
for lock in &locks[0..i] {
// safety: this lock was already acquired
- lock.unlock();
+ lock.raw_unlock();
}
return false;
}
@@ -28,12 +28,12 @@ pub unsafe fn ordered_try_read(locks: &[&dyn RawLock]) -> bool {
unsafe {
for (i, lock) in locks.iter().enumerate() {
// safety: we have the thread key
- let success = lock.try_read();
+ let success = lock.raw_try_read();
if !success {
for lock in &locks[0..i] {
// safety: this lock was already acquired
- lock.unlock_read();
+ lock.raw_unlock_read();
}
return false;
}
diff --git a/src/lockable.rs b/src/lockable.rs
index 0066cb4..b098b25 100644
--- a/src/lockable.rs
+++ b/src/lockable.rs
@@ -1,11 +1,8 @@
use std::mem::MaybeUninit;
-use crate::{
- mutex::{Mutex, MutexRef},
- rwlock::{ReadLock, RwLock, RwLockReadRef, RwLockWriteRef, WriteLock},
-};
+use crate::rwlock::{ReadLock, RwLock, RwLockReadRef, RwLockWriteRef, WriteLock};
-use lock_api::{RawMutex, RawRwLock};
+use lock_api::RawRwLock;
/// A raw lock type that may be locked and unlocked
///
@@ -21,7 +18,11 @@ use lock_api::{RawMutex, RawRwLock};
// because it'd be difficult to implement a separate type that takes a
// different kind of RawLock. But now the Sharable marker trait is needed to
// indicate if reads can be used.
-pub unsafe trait RawLock: Send + Sync {
+pub unsafe trait RawLock {
+ /// Causes all subsequent calls to the `lock` function on this lock to
+ /// panic. This does not affect anything currently holding the lock.
+ fn kill(&self);
+
/// Blocks until the lock is acquired
///
/// # Safety
@@ -31,7 +32,7 @@ pub unsafe trait RawLock: Send + Sync {
/// value is alive.
///
/// [`ThreadKey`]: `crate::ThreadKey`
- unsafe fn lock(&self);
+ unsafe fn raw_lock(&self);
/// Attempt to lock without blocking.
///
@@ -44,14 +45,14 @@ pub unsafe trait RawLock: Send + Sync {
/// value is alive.
///
/// [`ThreadKey`]: `crate::ThreadKey`
- unsafe fn try_lock(&self) -> bool;
+ unsafe fn raw_try_lock(&self) -> bool;
/// Releases the lock
///
/// # Safety
///
/// It is undefined behavior to use this if the lock is not acquired
- unsafe fn unlock(&self);
+ unsafe fn raw_unlock(&self);
/// Blocks until the data the lock protects can be safely read.
///
@@ -66,7 +67,7 @@ pub unsafe trait RawLock: Send + Sync {
/// value is alive.
///
/// [`ThreadKey`]: `crate::ThreadKey`
- unsafe fn read(&self);
+ unsafe fn raw_read(&self);
// Attempt to read without blocking.
///
@@ -83,14 +84,14 @@ pub unsafe trait RawLock: Send + Sync {
/// value is alive.
///
/// [`ThreadKey`]: `crate::ThreadKey`
- unsafe fn try_read(&self) -> bool;
+ unsafe fn raw_try_read(&self) -> bool;
/// Releases the lock after calling `read`.
///
/// # Safety
///
/// It is undefined behavior to use this if the read lock is not acquired
- unsafe fn unlock_read(&self);
+ unsafe fn raw_unlock_read(&self);
}
/// A type that may be locked and unlocked.
@@ -207,151 +208,6 @@ 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: RawMutex + Send + Sync> RawLock for Mutex<T, R> {
- unsafe fn lock(&self) {
- self.raw().lock()
- }
-
- unsafe fn try_lock(&self) -> bool {
- self.raw().try_lock()
- }
-
- unsafe fn unlock(&self) {
- self.raw().unlock()
- }
-
- // this is the closest thing to a read we can get, but Sharable isn't
- // implemented for this
- unsafe fn read(&self) {
- self.raw().lock()
- }
-
- unsafe fn try_read(&self) -> bool {
- self.raw().try_lock()
- }
-
- unsafe fn unlock_read(&self) {
- self.raw().unlock()
- }
-}
-
-unsafe impl<T: Send, R: RawRwLock + Send + Sync> RawLock for RwLock<T, R> {
- unsafe fn lock(&self) {
- self.raw().lock_exclusive()
- }
-
- unsafe fn try_lock(&self) -> bool {
- self.raw().try_lock_exclusive()
- }
-
- unsafe fn unlock(&self) {
- self.raw().unlock_exclusive()
- }
-
- unsafe fn read(&self) {
- self.raw().lock_shared()
- }
-
- unsafe fn try_read(&self) -> bool {
- self.raw().try_lock_shared()
- }
-
- unsafe fn unlock_read(&self) {
- self.raw().unlock_shared()
- }
-}
-
-unsafe impl<T: Send, R: RawMutex + Send + Sync> Lockable for Mutex<T, R> {
- type Guard<'g>
- = 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);
- }
-
- unsafe fn guard(&self) -> Self::Guard<'_> {
- MutexRef::new(self)
- }
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- MutexRef::new(self)
- }
-}
-
-unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for RwLock<T, R> {
- type Guard<'g>
- = RwLockWriteRef<'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);
- }
-
- unsafe fn guard(&self) -> Self::Guard<'_> {
- RwLockWriteRef::new(self)
- }
-
- unsafe fn read_guard(&self) -> Self::ReadGuard<'_> {
- RwLockReadRef::new(self)
- }
-}
-
-impl<T: Send, R: RawMutex + Send + Sync> LockableIntoInner for Mutex<T, R> {
- type Inner = T;
-
- fn into_inner(self) -> Self::Inner {
- self.into_inner()
- }
-}
-
-impl<T: Send, R: RawMutex + Send + Sync> LockableAsMut for Mutex<T, R> {
- type Inner<'a>
- = &'a mut T
- where
- Self: 'a;
-
- fn as_mut(&mut self) -> Self::Inner<'_> {
- self.get_mut()
- }
-}
-
-impl<T: Send, R: RawRwLock + Send + Sync> LockableIntoInner for RwLock<T, R> {
- type Inner = T;
-
- fn into_inner(self) -> Self::Inner {
- self.into_inner()
- }
-}
-
-impl<T: Send, R: RawRwLock + Send + Sync> LockableAsMut for RwLock<T, R> {
- type Inner<'a>
- = &'a mut T
- where
- Self: 'a;
-
- fn as_mut(&mut self) -> Self::Inner<'_> {
- AsMut::as_mut(self)
- }
-}
-
-unsafe impl<T: Send, R: RawRwLock + Send + Sync> Sharable for RwLock<T, R> {}
-
-unsafe impl<T: Send, R: RawMutex + Send + Sync> OwnedLockable for Mutex<T, R> {}
-
-unsafe impl<T: Send, R: RawRwLock + Send + Sync> OwnedLockable for RwLock<T, R> {}
-
unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for ReadLock<'_, T, R> {
type Guard<'g>
= RwLockReadRef<'g, T, R>
diff --git a/src/mutex.rs b/src/mutex.rs
index 51089c4..004e5d4 100644
--- a/src/mutex.rs
+++ b/src/mutex.rs
@@ -4,6 +4,7 @@ use std::marker::PhantomData;
use lock_api::RawMutex;
use crate::key::Keyable;
+use crate::poisonable::PoisonFlag;
mod guard;
mod mutex;
@@ -128,6 +129,7 @@ pub type ParkingMutex<T> = Mutex<T, parking_lot::RawMutex>;
/// [`ThreadKey`]: `crate::ThreadKey`
pub struct Mutex<T: ?Sized, R> {
raw: R,
+ poison: PoisonFlag,
data: UnsafeCell<T>,
}
diff --git a/src/mutex/guard.rs b/src/mutex/guard.rs
index 8b2b1aa..c255996 100644
--- a/src/mutex/guard.rs
+++ b/src/mutex/guard.rs
@@ -5,6 +5,7 @@ use std::ops::{Deref, DerefMut};
use lock_api::RawMutex;
use crate::key::Keyable;
+use crate::lockable::RawLock;
use super::{Mutex, MutexGuard, MutexRef};
@@ -27,7 +28,7 @@ impl<'a, T: ?Sized + 'a, R: RawMutex> Drop for MutexRef<'a, T, R> {
fn drop(&mut self) {
// safety: this guard is being destroyed, so the data cannot be
// accessed without locking again
- unsafe { self.0.force_unlock() }
+ unsafe { self.0.raw_unlock() }
}
}
diff --git a/src/mutex/mutex.rs b/src/mutex/mutex.rs
index 9707e2f..1130110 100644
--- a/src/mutex/mutex.rs
+++ b/src/mutex/mutex.rs
@@ -5,9 +5,99 @@ use std::marker::PhantomData;
use lock_api::RawMutex;
use crate::key::Keyable;
+use crate::lockable::{Lockable, LockableAsMut, LockableIntoInner, OwnedLockable, RawLock};
+use crate::poisonable::PoisonFlag;
use super::{Mutex, MutexGuard, MutexRef};
+unsafe impl<T: ?Sized, R: RawMutex> RawLock for Mutex<T, R> {
+ fn kill(&self) {
+ self.poison.poison();
+ }
+
+ unsafe fn raw_lock(&self) {
+ assert!(!self.poison.is_poisoned(), "The mutex has been killed");
+
+ self.raw.lock()
+ }
+
+ unsafe fn raw_try_lock(&self) -> bool {
+ if self.poison.is_poisoned() {
+ return false;
+ }
+
+ self.raw.try_lock()
+ }
+
+ unsafe fn raw_unlock(&self) {
+ self.raw.unlock()
+ }
+
+ // this is the closest thing to a read we can get, but Sharable isn't
+ // implemented for this
+ unsafe fn raw_read(&self) {
+ assert!(!self.poison.is_poisoned(), "The mutex has been killed");
+
+ self.raw.lock()
+ }
+
+ unsafe fn raw_try_read(&self) -> bool {
+ if self.poison.is_poisoned() {
+ return false;
+ }
+
+ self.raw.try_lock()
+ }
+
+ unsafe fn raw_unlock_read(&self) {
+ self.raw.unlock()
+ }
+}
+
+unsafe impl<T: Send, R: RawMutex + Send + Sync> Lockable for Mutex<T, R> {
+ type Guard<'g>
+ = 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);
+ }
+
+ 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> {
+ type Inner = T;
+
+ fn into_inner(self) -> Self::Inner {
+ self.into_inner()
+ }
+}
+
+impl<T: Send, R: RawMutex + Send + Sync> LockableAsMut for Mutex<T, R> {
+ type Inner<'a>
+ = &'a mut T
+ where
+ Self: 'a;
+
+ fn as_mut(&mut self) -> Self::Inner<'_> {
+ self.get_mut()
+ }
+}
+
+unsafe impl<T: Send, R: RawMutex + Send + Sync> OwnedLockable for Mutex<T, R> {}
+
impl<T, R: RawMutex> Mutex<T, R> {
/// Create a new unlocked `Mutex`.
///
@@ -22,6 +112,7 @@ impl<T, R: RawMutex> Mutex<T, R> {
pub const fn new(data: T) -> Self {
Self {
raw: R::INIT,
+ poison: PoisonFlag::new(),
data: UnsafeCell::new(data),
}
}
@@ -153,7 +244,8 @@ impl<T: ?Sized, R: RawMutex> Mutex<T, R> {
/// ```
pub fn lock<'s, 'k: 's, Key: Keyable>(&'s self, key: Key) -> MutexGuard<'s, 'k, T, Key, R> {
unsafe {
- self.raw.lock();
+ // safety: we have the thread key
+ self.raw_lock();
// safety: we just locked the mutex
MutexGuard::new(self, key)
@@ -192,15 +284,16 @@ impl<T: ?Sized, R: RawMutex> Mutex<T, R> {
&'s self,
key: Key,
) -> Option<MutexGuard<'s, 'k, T, Key, R>> {
- if self.raw.try_lock() {
- // safety: we just locked the mutex
- Some(unsafe { MutexGuard::new(self, key) })
- } else {
- None
+ unsafe {
+ // safety: we have the key to the mutex
+ self.raw_try_lock().then(||
+ // safety: we just locked the mutex
+ MutexGuard::new(self, key))
}
}
/// Returns `true` if the mutex is currently locked
+ #[cfg(test)]
pub(crate) fn is_locked(&self) -> bool {
self.raw.is_locked()
}
@@ -208,17 +301,7 @@ impl<T: ?Sized, R: RawMutex> Mutex<T, R> {
/// Lock without a [`ThreadKey`]. It is undefined behavior to do this without
/// owning the [`ThreadKey`].
pub(crate) unsafe fn try_lock_no_key(&self) -> Option<MutexRef<'_, T, R>> {
- self.raw.try_lock().then_some(MutexRef(self, PhantomData))
- }
-
- /// Forcibly unlocks the `Lock`.
- ///
- /// # Safety
- ///
- /// This should only be called if there are no references to any
- /// [`MutexGuard`]s for this mutex in the program.
- pub(super) unsafe fn force_unlock(&self) {
- self.raw.unlock();
+ self.raw_try_lock().then_some(MutexRef(self, PhantomData))
}
/// Consumes the [`MutexGuard`], and consequently unlocks its `Mutex`.
@@ -238,7 +321,7 @@ impl<T: ?Sized, R: RawMutex> Mutex<T, R> {
/// ```
pub fn unlock<'a, 'k: 'a, Key: Keyable + 'k>(guard: MutexGuard<'a, 'k, T, Key, R>) -> Key {
unsafe {
- guard.mutex.0.force_unlock();
+ guard.mutex.0.raw_unlock();
}
guard.thread_key
}
diff --git a/src/poisonable.rs b/src/poisonable.rs
index ec6de82..f9152d1 100644
--- a/src/poisonable.rs
+++ b/src/poisonable.rs
@@ -9,7 +9,7 @@ mod poisonable;
/// A flag indicating if a lock is poisoned or not. The implementation differs
/// depending on whether panics are set to unwind or abort.
#[derive(Debug, Default)]
-struct PoisonFlag(#[cfg(panic = "unwind")] AtomicBool);
+pub(crate) struct PoisonFlag(#[cfg(panic = "unwind")] AtomicBool);
/// A wrapper around [`Lockable`] types which will enable poisoning.
///
diff --git a/src/poisonable/flag.rs b/src/poisonable/flag.rs
index be38a38..a692685 100644
--- a/src/poisonable/flag.rs
+++ b/src/poisonable/flag.rs
@@ -16,6 +16,10 @@ impl PoisonFlag {
pub fn clear_poison(&self) {
self.0.store(false, Relaxed)
}
+
+ pub fn poison(&self) {
+ self.0.store(true, Relaxed);
+ }
}
#[cfg(not(panic = "unwind"))]
diff --git a/src/poisonable/guard.rs b/src/poisonable/guard.rs
index 30a9b70..6438c2d 100644
--- a/src/poisonable/guard.rs
+++ b/src/poisonable/guard.rs
@@ -1,7 +1,6 @@
use std::fmt::{Debug, Display};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
-use std::sync::atomic::Ordering::Relaxed;
use crate::Keyable;
@@ -23,7 +22,7 @@ impl<Guard> Drop for PoisonRef<'_, Guard> {
fn drop(&mut self) {
#[cfg(panic = "unwind")]
if std::thread::panicking() {
- self.flag.0.store(true, Relaxed);
+ self.flag.poison();
}
}
}
diff --git a/src/poisonable/poisonable.rs b/src/poisonable/poisonable.rs
index ddd8038..581fb2f 100644
--- a/src/poisonable/poisonable.rs
+++ b/src/poisonable/poisonable.rs
@@ -12,28 +12,32 @@ use super::{
};
unsafe impl<L: Lockable + RawLock> RawLock for Poisonable<L> {
- unsafe fn lock(&self) {
- self.inner.lock()
+ fn kill(&self) {
+ self.inner.kill()
}
- unsafe fn try_lock(&self) -> bool {
- self.inner.try_lock()
+ unsafe fn raw_lock(&self) {
+ self.inner.raw_lock()
}
- unsafe fn unlock(&self) {
- self.inner.unlock()
+ unsafe fn raw_try_lock(&self) -> bool {
+ self.inner.raw_try_lock()
}
- unsafe fn read(&self) {
- self.inner.read()
+ unsafe fn raw_unlock(&self) {
+ self.inner.raw_unlock()
}
- unsafe fn try_read(&self) -> bool {
- self.inner.try_read()
+ unsafe fn raw_read(&self) {
+ self.inner.raw_read()
}
- unsafe fn unlock_read(&self) {
- self.inner.unlock_read()
+ unsafe fn raw_try_read(&self) -> bool {
+ self.inner.raw_try_read()
+ }
+
+ unsafe fn raw_unlock_read(&self) {
+ self.inner.raw_unlock_read()
}
}
@@ -285,7 +289,7 @@ impl<L: Lockable + RawLock> Poisonable<L> {
key: Key,
) -> PoisonResult<PoisonGuard<'flag, 'key, L::Guard<'flag>, Key>> {
unsafe {
- self.inner.lock();
+ self.inner.raw_lock();
self.guard(key)
}
}
@@ -339,7 +343,7 @@ impl<L: Lockable + RawLock> Poisonable<L> {
key: Key,
) -> TryLockPoisonableResult<'flag, 'key, L::Guard<'flag>, Key> {
unsafe {
- if self.inner.try_lock() {
+ if self.inner.raw_try_lock() {
Ok(self.guard(key)?)
} else {
Err(TryLockPoisonableError::WouldBlock(key))
@@ -426,7 +430,7 @@ impl<L: Sharable + RawLock> Poisonable<L> {
key: Key,
) -> PoisonResult<PoisonGuard<'flag, 'key, L::ReadGuard<'flag>, Key>> {
unsafe {
- self.inner.read();
+ self.inner.raw_read();
self.read_guard(key)
}
}
@@ -473,7 +477,7 @@ impl<L: Sharable + RawLock> Poisonable<L> {
key: Key,
) -> TryLockPoisonableResult<'flag, 'key, L::ReadGuard<'flag>, Key> {
unsafe {
- if self.inner.try_read() {
+ if self.inner.raw_try_read() {
Ok(self.read_guard(key)?)
} else {
Err(TryLockPoisonableError::WouldBlock(key))
diff --git a/src/rwlock.rs b/src/rwlock.rs
index c1d9a78..9b65a0b 100644
--- a/src/rwlock.rs
+++ b/src/rwlock.rs
@@ -4,6 +4,7 @@ use std::marker::PhantomData;
use lock_api::RawRwLock;
use crate::key::Keyable;
+use crate::poisonable::PoisonFlag;
mod rwlock;
@@ -46,6 +47,7 @@ pub type ParkingRwLock<T> = RwLock<T, parking_lot::RawRwLock>;
/// [`DerefMut`]: `std::ops::DerefMut`
pub struct RwLock<T: ?Sized, R> {
raw: R,
+ poison: PoisonFlag,
data: UnsafeCell<T>,
}
diff --git a/src/rwlock/read_guard.rs b/src/rwlock/read_guard.rs
index 1eb8bfc..0668dca 100644
--- a/src/rwlock/read_guard.rs
+++ b/src/rwlock/read_guard.rs
@@ -5,6 +5,7 @@ use std::ops::Deref;
use lock_api::RawRwLock;
use crate::key::Keyable;
+use crate::lockable::RawLock;
use super::{RwLock, RwLockReadGuard, RwLockReadRef};
@@ -41,7 +42,7 @@ impl<'a, T: ?Sized + 'a, R: RawRwLock> Drop for RwLockReadRef<'a, T, R> {
fn drop(&mut self) {
// safety: this guard is being destroyed, so the data cannot be
// accessed without locking again
- unsafe { self.0.force_unlock_read() }
+ unsafe { self.0.raw_unlock_read() }
}
}
diff --git a/src/rwlock/rwlock.rs b/src/rwlock/rwlock.rs
index 063ab68..86005e3 100644
--- a/src/rwlock/rwlock.rs
+++ b/src/rwlock/rwlock.rs
@@ -4,8 +4,106 @@ use std::{cell::UnsafeCell, marker::PhantomData};
use lock_api::RawRwLock;
use crate::key::Keyable;
+use crate::lockable::{
+ Lockable, LockableAsMut, LockableIntoInner, OwnedLockable, RawLock, Sharable,
+};
-use super::{RwLock, RwLockReadGuard, RwLockReadRef, RwLockWriteGuard, RwLockWriteRef};
+use super::{PoisonFlag, RwLock, RwLockReadGuard, RwLockReadRef, RwLockWriteGuard, RwLockWriteRef};
+
+unsafe impl<T: ?Sized, R: RawRwLock> RawLock for RwLock<T, R> {
+ fn kill(&self) {
+ self.poison.poison();
+ }
+
+ unsafe fn raw_lock(&self) {
+ assert!(
+ !self.poison.is_poisoned(),
+ "The read-write lock has been killed"
+ );
+
+ self.raw.lock_exclusive()
+ }
+
+ unsafe fn raw_try_lock(&self) -> bool {
+ if self.poison.is_poisoned() {
+ return false;
+ }
+
+ self.raw.try_lock_exclusive()
+ }
+
+ unsafe fn raw_unlock(&self) {
+ self.raw.unlock_exclusive()
+ }
+
+ unsafe fn raw_read(&self) {
+ assert!(
+ !self.poison.is_poisoned(),
+ "The read-write lock has been killed"
+ );
+
+ self.raw.lock_shared()
+ }
+
+ unsafe fn raw_try_read(&self) -> bool {
+ if self.poison.is_poisoned() {
+ return false;
+ }
+
+ self.raw.try_lock_shared()
+ }
+
+ unsafe fn raw_unlock_read(&self) {
+ self.raw.unlock_shared()
+ }
+}
+
+unsafe impl<T: Send, R: RawRwLock + Send + Sync> Lockable for RwLock<T, R> {
+ type Guard<'g>
+ = RwLockWriteRef<'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);
+ }
+
+ 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> {
+ type Inner = T;
+
+ fn into_inner(self) -> Self::Inner {
+ self.into_inner()
+ }
+}
+
+impl<T: Send, R: RawRwLock + Send + Sync> LockableAsMut for RwLock<T, R> {
+ type Inner<'a>
+ = &'a mut T
+ where
+ Self: 'a;
+
+ fn as_mut(&mut self) -> Self::Inner<'_> {
+ AsMut::as_mut(self)
+ }
+}
+
+unsafe impl<T: Send, R: RawRwLock + Send + Sync> Sharable for RwLock<T, R> {}
+
+unsafe impl<T: Send, R: RawRwLock + Send + Sync> OwnedLockable for RwLock<T, R> {}
impl<T, R: RawRwLock> RwLock<T, R> {
/// Creates a new instance of an `RwLock<T>` which is unlocked.
@@ -21,6 +119,7 @@ impl<T, R: RawRwLock> RwLock<T, R> {
pub const fn new(data: T) -> Self {
Self {
data: UnsafeCell::new(data),
+ poison: PoisonFlag::new(),
raw: R::INIT,
}
}
@@ -142,7 +241,7 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
key: Key,
) -> RwLockReadGuard<'s, 'key, T, Key, R> {
unsafe {
- self.raw.lock_shared();
+ self.raw_read();
// safety: the lock is locked first
RwLockReadGuard::new(self, key)
@@ -174,7 +273,7 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
key: Key,
) -> Option<RwLockReadGuard<'s, 'key, T, Key, R>> {
unsafe {
- if self.raw.try_lock_shared() {
+ if self.raw_try_read() {
// safety: the lock is locked first
Some(RwLockReadGuard::new(self, key))
} else {
@@ -186,7 +285,7 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
/// Attempts to create a shared lock without a key. Locking this without
/// exclusive access to the key is undefined behavior.
pub(crate) unsafe fn try_read_no_key(&self) -> Option<RwLockReadRef<'_, T, R>> {
- if self.raw.try_lock_shared() {
+ if self.raw_try_read() {
// safety: the lock is locked first
Some(RwLockReadRef(self, PhantomData))
} else {
@@ -196,8 +295,9 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
/// Attempts to create an exclusive lock without a key. Locking this
/// without exclusive access to the key is undefined behavior.
+ #[cfg(test)]
pub(crate) unsafe fn try_write_no_key(&self) -> Option<RwLockWriteRef<'_, T, R>> {
- if self.raw.try_lock_exclusive() {
+ if self.raw_try_lock() {
// safety: the lock is locked first
Some(RwLockWriteRef(self, PhantomData))
} else {
@@ -235,7 +335,7 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
key: Key,
) -> RwLockWriteGuard<'s, 'key, T, Key, R> {
unsafe {
- self.raw.lock_exclusive();
+ self.raw_lock();
// safety: the lock is locked first
RwLockWriteGuard::new(self, key)
@@ -268,7 +368,7 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
key: Key,
) -> Option<RwLockWriteGuard<'s, 'key, T, Key, R>> {
unsafe {
- if self.raw.try_lock_exclusive() {
+ if self.raw_try_lock() {
// safety: the lock is locked first
Some(RwLockWriteGuard::new(self, key))
} else {
@@ -278,22 +378,11 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
}
/// Returns `true` if the rwlock is currently locked in any way
+ #[cfg(test)]
pub(crate) fn is_locked(&self) -> bool {
self.raw.is_locked()
}
- /// Unlocks shared access on the `RwLock`. This is undefined behavior is
- /// the data is still accessible.
- pub(super) unsafe fn force_unlock_read(&self) {
- self.raw.unlock_shared();
- }
-
- /// Unlocks exclusive access on the `RwLock`. This is undefined behavior is
- /// the data is still accessible.
- pub(super) unsafe fn force_unlock_write(&self) {
- self.raw.unlock_exclusive();
- }
-
/// Immediately drops the guard, and consequently releases the shared lock.
///
/// This function is equivalent to calling [`drop`] on the guard, except
@@ -316,7 +405,7 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
guard: RwLockReadGuard<'_, 'key, T, Key, R>,
) -> Key {
unsafe {
- guard.rwlock.0.force_unlock_read();
+ guard.rwlock.0.raw_unlock_read();
}
guard.thread_key
}
@@ -344,7 +433,7 @@ impl<T: ?Sized, R: RawRwLock> RwLock<T, R> {
guard: RwLockWriteGuard<'_, 'key, T, Key, R>,
) -> Key {
unsafe {
- guard.rwlock.0.force_unlock_write();
+ guard.rwlock.0.raw_unlock();
}
guard.thread_key
}
diff --git a/src/rwlock/write_guard.rs b/src/rwlock/write_guard.rs
index 9ffea39..31ed14a 100644
--- a/src/rwlock/write_guard.rs
+++ b/src/rwlock/write_guard.rs
@@ -5,6 +5,7 @@ use std::ops::{Deref, DerefMut};
use lock_api::RawRwLock;
use crate::key::Keyable;
+use crate::lockable::RawLock;
use super::{RwLock, RwLockWriteGuard, RwLockWriteRef};
@@ -56,7 +57,7 @@ impl<'a, T: ?Sized + 'a, R: RawRwLock> Drop for RwLockWriteRef<'a, T, R> {
fn drop(&mut self) {
// safety: this guard is being destroyed, so the data cannot be
// accessed without locking again
- unsafe { self.0.force_unlock_write() }
+ unsafe { self.0.raw_unlock() }
}
}