summaryrefslogtreecommitdiff
path: root/src/lockable.rs
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2024-03-10 18:13:20 -0400
committerMica White <botahamec@outlook.com>2024-03-10 18:13:20 -0400
commit0c519b6c7801aa6a085551c8e144f0336e615870 (patch)
tree19063baecb0b50266c654f4809101e856ee89082 /src/lockable.rs
parent61d709c211132adcc5158ded77c17d690ad5f8da (diff)
Better librarification
Diffstat (limited to 'src/lockable.rs')
-rw-r--r--src/lockable.rs79
1 files changed, 52 insertions, 27 deletions
diff --git a/src/lockable.rs b/src/lockable.rs
index 3c217c4..d3367fa 100644
--- a/src/lockable.rs
+++ b/src/lockable.rs
@@ -7,28 +7,6 @@ use crate::{
use lock_api::{RawMutex, RawRwLock};
-mod sealed {
- use super::Lockable as L;
- #[allow(clippy::wildcard_imports)]
- use super::*;
-
- pub trait Sealed {}
- impl<'a, T, R: RawMutex + 'a> Sealed for Mutex<T, R> {}
- impl<'a, T, R: RawRwLock + 'a> Sealed for RwLock<T, R> {}
- impl<'a, T, R: RawRwLock + 'a> Sealed for ReadLock<'a, T, R> {}
- impl<'a, T, R: RawRwLock + 'a> Sealed for WriteLock<'a, T, R> {}
- impl<T: Sealed> Sealed for &T {}
- impl<T: Sealed> Sealed for &mut T {}
- impl<'a, A: L<'a>> Sealed for (A,) {}
- impl<'a, A: L<'a>, B: L<'a>> Sealed for (A, B) {}
- impl<'a, A: L<'a>, B: L<'a>, C: L<'a>> Sealed for (A, B, C) {}
- impl<'a, A: L<'a>, B: L<'a>, C: L<'a>, D: L<'a>> Sealed for (A, B, C, D) {}
- impl<'a, A: L<'a>, B: L<'a>, C: L<'a>, D: L<'a>, E: L<'a>> Sealed for (A, B, C, D, E) {}
- impl<'a, A: L<'a>, B: L<'a>, C: L<'a>, D: L<'a>, E: L<'a>, F: L<'a>> Sealed for (A, B, C, D, E, F) {}
- impl<'a, T: Lockable<'a>, const N: usize> Sealed for [T; N] {}
- impl<'a, T: Lockable<'a>> Sealed for Vec<T> {}
-}
-
/// A type that may be locked and unlocked, and is known to be the only valid
/// instance of the lock.
///
@@ -45,12 +23,13 @@ pub unsafe trait OwnedLockable<'a>: Lockable<'a> {}
/// A deadlock must never occur. The `unlock` method must correctly unlock the
/// 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 {
+pub unsafe trait Lockable<'a> {
/// 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
+ #[must_use]
fn get_ptrs(&self) -> Vec<usize>;
/// Blocks until the lock is acquired
@@ -62,7 +41,7 @@ pub unsafe trait Lockable<'a>: sealed::Sealed {
/// which should last as long as the return value is alive.
/// * Call this on multiple locks without unlocking first.
///
- /// [`ThreadKey`]: `crate::key::ThreadKey`
+ /// [`ThreadKey`]: `crate::ThreadKey`
unsafe fn lock(&'a self) -> Self::Output;
/// Attempt to lock without blocking.
@@ -75,7 +54,7 @@ pub unsafe trait Lockable<'a>: sealed::Sealed {
/// access to the [`ThreadKey`], which should last as long as the return
/// value is alive.
///
- /// [`ThreadKey`]: `crate::key::ThreadKey`
+ /// [`ThreadKey`]: `crate::ThreadKey`
unsafe fn try_lock(&'a self) -> Option<Self::Output>;
}
@@ -153,7 +132,7 @@ 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]
+ vec![self.as_ref() as *const RwLock<T, R> as usize]
}
unsafe fn lock(&'a self) -> Self::Output {
@@ -169,7 +148,7 @@ 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]
+ vec![self.as_ref() as *const RwLock<T, R> as usize]
}
unsafe fn lock(&'a self) -> Self::Output {
@@ -562,6 +541,51 @@ 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 Output = Box<[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());
+ if self.is_empty() {
+ return outputs.into_boxed_slice();
+ }
+
+ outputs.push(self[0].lock());
+ for lock in self.iter().skip(1) {
+ if let Some(guard) = lock.try_lock() {
+ outputs.push(guard);
+ } else {
+ continue 'outer;
+ };
+ }
+
+ return outputs.into_boxed_slice();
+ }
+ }
+
+ unsafe fn try_lock(&'a self) -> Option<Self::Output> {
+ let mut outputs = Vec::with_capacity(self.len());
+ for lock in &**self {
+ if let Some(guard) = lock.try_lock() {
+ outputs.push(guard);
+ } else {
+ return None;
+ };
+ }
+
+ Some(outputs.into_boxed_slice())
+ }
+}
+
unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec<T> {
type Output = Vec<T::Output>;
@@ -608,4 +632,5 @@ unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec<T> {
}
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<T> {}