summaryrefslogtreecommitdiff
path: root/src/lockable.rs
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2024-03-13 22:44:46 -0400
committerMica White <botahamec@outlook.com>2024-03-13 22:44:46 -0400
commit7bd236853ef5ae705328c8fdc492cf60fc6887c1 (patch)
treeec4e9dced562fdae618b98ac704074c0ddc9cc41 /src/lockable.rs
parent7c6f49b6570669098938dc332a4f3e85dd3d217d (diff)
Lockable overhaul
Diffstat (limited to 'src/lockable.rs')
-rw-r--r--src/lockable.rs706
1 files changed, 246 insertions, 460 deletions
diff --git a/src/lockable.rs b/src/lockable.rs
index 086ab33..a09b84b 100644
--- a/src/lockable.rs
+++ b/src/lockable.rs
@@ -7,15 +7,6 @@ use crate::{
use lock_api::{RawMutex, RawRwLock};
-/// A type that may be locked and unlocked, and is known to be the only valid
-/// instance of the lock.
-///
-/// # Safety
-///
-/// 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> {}
-
/// A type that may be locked and unlocked
///
/// # Safety
@@ -23,30 +14,21 @@ 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> {
- /// 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>;
-
+pub unsafe trait Lock: Send + Sync {
/// Blocks until the lock is acquired
///
/// # Safety
///
- /// It is undefined behavior to:
- /// * Use this without ownership or mutable access to the [`ThreadKey`],
- /// which should last as long as the return value is alive.
- /// * Call this on multiple locks without unlocking first.
+ /// It is undefined behavior to use this without ownership or mutable
+ /// access to the [`ThreadKey`], which should last as long as the return
+ /// value is alive.
///
/// [`ThreadKey`]: `crate::ThreadKey`
- unsafe fn lock(&'a self) -> Self::Output;
+ unsafe fn lock(&self);
/// Attempt to lock without blocking.
///
- /// Returns `Some` if successful, `None` otherwise.
+ /// Returns `true` if successful, `false` otherwise.
///
/// # Safety
///
@@ -55,304 +37,225 @@ pub unsafe trait Lockable<'a> {
/// value is alive.
///
/// [`ThreadKey`]: `crate::ThreadKey`
- unsafe fn try_lock(&'a self) -> Option<Self::Output>;
+ unsafe fn 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);
+}
+
+pub unsafe trait Lockable<'a> {
+ /// The guard returned that does not hold a key
+ type Guard;
+
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>);
+
+ #[must_use]
+ unsafe fn guard(&'a self) -> Self::Guard;
}
-unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &T {
- type Output = T::Output;
+/// A type that may be locked and unlocked, and is known to be the only valid
+/// instance of the lock.
+///
+/// # Safety
+///
+/// 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> {}
- fn get_ptrs(&self) -> Vec<usize> {
- (*self).get_ptrs()
+unsafe impl<T: Send, R: RawMutex + Send + Sync> Lock for Mutex<T, R> {
+ unsafe fn lock(&self) {
+ self.raw().lock()
}
- unsafe fn lock(&'a self) -> Self::Output {
- (*self).lock()
+ unsafe fn try_lock(&self) -> bool {
+ self.raw().try_lock()
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- (*self).try_lock()
+ unsafe fn unlock(&self) {
+ self.raw().unlock()
}
}
-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 impl<T: Send, R: RawRwLock + Send + Sync> Lock for RwLock<T, R> {
+ unsafe fn lock(&self) {
+ self.raw().lock_exclusive()
}
- unsafe fn lock(&'a self) -> Self::Output {
- (**self).lock()
+ unsafe fn try_lock(&self) -> bool {
+ self.raw().try_lock_exclusive()
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- (**self).try_lock()
+ unsafe fn unlock(&self) {
+ self.raw().unlock_exclusive()
}
}
-unsafe impl<'a, T: OwnedLockable<'a>> OwnedLockable<'a> for &mut T {}
+unsafe impl<'a, T: Send + 'a, R: RawMutex + Send + Sync + 'a> Lockable<'a> for Mutex<T, R> {
+ type Guard = MutexRef<'a, T, R>;
-unsafe impl<'a, T: 'a, R: RawMutex + 'a> Lockable<'a> for Mutex<T, R> {
- type Output = MutexRef<'a, T, R>;
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ ptrs.push(self);
+ }
- fn get_ptrs(&self) -> Vec<usize> {
- vec![self as *const Self as usize]
+ unsafe fn guard(&'a self) -> Self::Guard {
+ MutexRef::new(self)
}
+}
- unsafe fn lock(&'a self) -> Self::Output {
- self.lock_no_key()
+unsafe impl<'a, T: Send + 'a, R: RawRwLock + Send + Sync + 'a> Lockable<'a> for RwLock<T, R> {
+ type Guard = RwLockWriteRef<'a, T, R>;
+
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ ptrs.push(self);
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- self.try_lock_no_key()
+ unsafe fn guard(&'a self) -> Self::Guard {
+ RwLockWriteRef::new(self)
}
}
-unsafe impl<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for RwLock<T, R> {
- type Output = RwLockWriteRef<'a, T, R>;
+unsafe impl<'a, T: Send + 'a, R: RawMutex + Send + Sync + 'a> OwnedLockable<'a> for Mutex<T, R> {}
- fn get_ptrs(&self) -> Vec<usize> {
- vec![self as *const Self as usize]
- }
+unsafe impl<'a, T: Send + 'a, R: RawRwLock + Send + Sync + 'a> OwnedLockable<'a> for RwLock<T, R> {}
+
+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 fn lock(&'a self) -> Self::Output {
- self.write_no_key()
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ ptrs.push(self.as_ref());
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- self.try_write_no_key()
+ unsafe fn guard(&'a self) -> Self::Guard {
+ RwLockReadRef::new(self.as_ref())
}
}
-unsafe impl<'a, T: 'a, R: RawMutex + 'a> OwnedLockable<'a> for Mutex<T, R> {}
-
-unsafe impl<'a, T: 'a, R: RawRwLock + 'a> OwnedLockable<'a> for RwLock<T, R> {}
+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<'a, T: 'a, R: RawRwLock + 'a> Lockable<'a> for ReadLock<'a, T, R> {
- type Output = RwLockReadRef<'a, T, R>;
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ ptrs.push(self.as_ref());
+ }
- fn get_ptrs(&self) -> Vec<usize> {
- vec![self.as_ref() as *const RwLock<T, R> as usize]
+ unsafe fn guard(&'a self) -> Self::Guard {
+ RwLockWriteRef::new(self.as_ref())
}
+}
- unsafe fn lock(&'a self) -> Self::Output {
- self.lock_no_key()
+unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &'a T {
+ type Guard = T::Guard;
+
+ fn get_ptrs(&self, ptrs: &mut Vec<&'a dyn Lock>) {
+ (*self).get_ptrs(ptrs);
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- self.try_lock_no_key()
+ unsafe fn guard(&self) -> Self::Guard {
+ (*self).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.as_ref() as *const RwLock<T, R> as usize]
- }
+unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for &mut T {
+ type Guard = T::Guard;
- unsafe fn lock(&'a self) -> Self::Output {
- self.lock_no_key()
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ (**self).get_ptrs(ptrs)
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- self.try_lock_no_key()
+ unsafe fn guard(&'a self) -> Self::Guard {
+ (**self).guard()
}
}
-unsafe impl<'a, A: Lockable<'a>> Lockable<'a> for (A,) {
- type Output = (A::Output,);
+unsafe impl<'a, T: OwnedLockable<'a>> OwnedLockable<'a> for &mut T {}
- fn get_ptrs(&self) -> Vec<usize> {
- let mut ptrs = Vec::with_capacity(1);
- ptrs.append(&mut self.0.get_ptrs());
- ptrs
- }
+unsafe impl<'a, A: Lockable<'a>> Lockable<'a> for (A,) {
+ type Guard = (A::Guard,);
- unsafe fn lock(&'a self) -> Self::Output {
- (self.0.lock(),)
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ self.0.get_ptrs(ptrs);
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- self.0.try_lock().map(|a| (a,))
+ unsafe fn guard(&'a self) -> Self::Guard {
+ (self.0.guard(),)
}
}
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
- }
+ type Guard = (A::Guard, B::Guard);
- unsafe fn lock(&'a self) -> Self::Output {
- loop {
- let lock0 = self.0.lock();
- let Some(lock1) = self.1.try_lock() else {
- continue;
- };
-
- return (lock0, lock1);
- }
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ self.0.get_ptrs(ptrs);
+ self.1.get_ptrs(ptrs);
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- let Some(lock0) = self.0.try_lock() else {
- return None;
- };
- let Some(lock1) = self.1.try_lock() else {
- return None;
- };
-
- Some((lock0, lock1))
+ unsafe fn guard(&'a 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 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 {
- continue;
- };
- let Some(lock2) = self.2.try_lock() else {
- continue;
- };
-
- return (lock0, lock1, lock2);
- }
- }
+ type Guard = (A::Guard, B::Guard, C::Guard);
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- let Some(lock0) = self.0.try_lock() else {
- return None;
- };
- let Some(lock1) = self.1.try_lock() else {
- return None;
- };
- let Some(lock2) = self.2.try_lock() else {
- return None;
- };
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ self.0.get_ptrs(ptrs);
+ self.1.get_ptrs(ptrs);
+ self.2.get_ptrs(ptrs);
+ }
- Some((lock0, lock1, lock2))
+ unsafe fn guard(&'a 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 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 {
- continue;
- };
- let Some(lock2) = self.2.try_lock() else {
- continue;
- };
- let Some(lock3) = self.3.try_lock() else {
- continue;
- };
-
- return (lock0, lock1, lock2, lock3);
- }
- }
+ type Guard = (A::Guard, B::Guard, C::Guard, D::Guard);
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- let Some(lock0) = self.0.try_lock() else {
- return None;
- };
- let Some(lock1) = self.1.try_lock() else {
- return None;
- };
- let Some(lock2) = self.2.try_lock() else {
- return None;
- };
- let Some(lock3) = self.3.try_lock() else {
- return None;
- };
+ fn get_ptrs(&'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);
+ }
- Some((lock0, lock1, lock2, lock3))
+ unsafe fn guard(&'a self) -> Self::Guard {
+ (
+ self.0.guard(),
+ self.1.guard(),
+ self.2.guard(),
+ self.3.guard(),
+ )
}
}
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)
{
- 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 {
- continue;
- };
- let Some(lock2) = self.2.try_lock() else {
- continue;
- };
- let Some(lock3) = self.3.try_lock() else {
- continue;
- };
- let Some(lock4) = self.4.try_lock() else {
- continue;
- };
-
- return (lock0, lock1, lock2, lock3, lock4);
- }
+ type Guard = (A::Guard, B::Guard, C::Guard, D::Guard, E::Guard);
+
+ fn get_ptrs(&'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);
+ self.4.get_ptrs(ptrs);
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- let Some(lock0) = self.0.try_lock() else {
- return None;
- };
- let Some(lock1) = self.1.try_lock() else {
- return None;
- };
- let Some(lock2) = self.2.try_lock() else {
- return None;
- };
- let Some(lock3) = self.3.try_lock() else {
- return None;
- };
- let Some(lock4) = self.4.try_lock() else {
- return None;
- };
-
- Some((lock0, lock1, lock2, lock3, lock4))
+ unsafe fn guard(&'a self) -> Self::Guard {
+ (
+ self.0.guard(),
+ self.1.guard(),
+ self.2.guard(),
+ self.3.guard(),
+ self.4.guard(),
+ )
}
}
@@ -366,79 +269,81 @@ unsafe impl<
F: Lockable<'a>,
> Lockable<'a> for (A, B, C, D, E, F)
{
- type Output = (
- A::Output,
- B::Output,
- C::Output,
- D::Output,
- E::Output,
- 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 {
- continue;
- };
- let Some(lock2) = self.2.try_lock() else {
- continue;
- };
- let Some(lock3) = self.3.try_lock() else {
- continue;
- };
- let Some(lock4) = self.4.try_lock() else {
- continue;
- };
- let Some(lock5) = self.5.try_lock() else {
- continue;
- };
-
- return (lock0, lock1, lock2, lock3, lock4, lock5);
- }
+ 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>) {
+ self.0.get_ptrs(ptrs);
+ self.1.get_ptrs(ptrs);
+ self.2.get_ptrs(ptrs);
+ self.3.get_ptrs(ptrs);
+ self.4.get_ptrs(ptrs);
+ self.5.get_ptrs(ptrs);
+ }
+
+ unsafe fn guard(&'a self) -> Self::Guard {
+ (
+ self.0.guard(),
+ self.1.guard(),
+ self.2.guard(),
+ self.3.guard(),
+ self.4.guard(),
+ self.5.guard(),
+ )
}
+}
+
+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)
+{
+ type Guard = (
+ A::Guard,
+ B::Guard,
+ C::Guard,
+ D::Guard,
+ E::Guard,
+ F::Guard,
+ G::Guard,
+ );
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- let Some(lock0) = self.0.try_lock() else {
- return None;
- };
- let Some(lock1) = self.1.try_lock() else {
- return None;
- };
- let Some(lock2) = self.2.try_lock() else {
- return None;
- };
- let Some(lock3) = self.3.try_lock() else {
- return None;
- };
- let Some(lock4) = self.4.try_lock() else {
- return None;
- };
- let Some(lock5) = self.5.try_lock() else {
- return None;
- };
-
- Some((lock0, lock1, lock2, lock3, lock4, lock5))
+ fn get_ptrs(&'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);
+ self.4.get_ptrs(ptrs);
+ self.5.get_ptrs(ptrs);
+ self.6.get_ptrs(ptrs);
+ }
+
+ unsafe fn guard(&'a self) -> Self::Guard {
+ (
+ self.0.guard(),
+ self.1.guard(),
+ self.2.guard(),
+ self.3.guard(),
+ self.4.guard(),
+ self.5.guard(),
+ self.6.guard(),
+ )
}
}
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<'a, A: OwnedLockable<'a>, B: OwnedLockable<'a>, C: OwnedLockable<'a>> OwnedLockable<'a>
for (A, B, C)
{
}
+
unsafe impl<
'a,
A: OwnedLockable<'a>,
@@ -448,6 +353,7 @@ unsafe impl<
> OwnedLockable<'a> for (A, B, C, D)
{
}
+
unsafe impl<
'a,
A: OwnedLockable<'a>,
@@ -458,6 +364,7 @@ unsafe impl<
> OwnedLockable<'a> for (A, B, C, D, E)
{
}
+
unsafe impl<
'a,
A: OwnedLockable<'a>,
@@ -470,194 +377,73 @@ unsafe impl<
{
}
+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)
+{
+}
+
unsafe impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] {
- type Output = [T::Output; N];
+ type Guard = [T::Guard; N];
- fn get_ptrs(&self) -> Vec<usize> {
- let mut ptrs = Vec::with_capacity(N);
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
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],
- upto: usize,
- ) {
- for (i, guard) in guards.into_iter().enumerate() {
- if i == upto {
- break;
- }
- drop(guard.assume_init());
- }
- }
-
- let mut first_idx = 0;
- 'outer: loop {
- let mut outputs = MaybeUninit::<[MaybeUninit<T::Output>; N]>::uninit().assume_init();
- if N == 0 {
- return outputs.map(|mu| mu.assume_init());
- }
-
- outputs[0].write(self[0].lock());
- for i in 0..N {
- if first_idx == i {
- continue;
- }
-
- match self[i].try_lock() {
- Some(guard) => outputs[i].write(guard),
- None => {
- unlock_partial::<T, N>(outputs, i);
- first_idx = i;
- continue 'outer;
- }
- };
- }
-
- return outputs.map(|mu| mu.assume_init());
+ lock.get_ptrs(ptrs);
}
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- unsafe fn unlock_partial<'a, T: Lockable<'a>, const N: usize>(
- guards: [MaybeUninit<T::Output>; N],
- upto: usize,
- ) {
- for (i, guard) in guards.into_iter().enumerate() {
- if i == upto {
- break;
- }
- drop(guard.assume_init());
- }
- }
-
- let mut outputs = MaybeUninit::<[MaybeUninit<T::Output>; N]>::uninit().assume_init();
+ unsafe fn guard(&'a self) -> Self::Guard {
+ let mut guards = MaybeUninit::<[MaybeUninit<T::Guard>; N]>::uninit().assume_init();
for i in 0..N {
- match self[i].try_lock() {
- Some(guard) => outputs[i].write(guard),
- None => {
- unlock_partial::<T, N>(outputs, i);
- return None;
- }
- };
+ guards[i].write(self[i].guard());
}
- Some(outputs.map(|mu| mu.assume_init()))
+ guards.map(|g| g.assume_init())
}
}
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
- }
+ type Guard = Box<[T::Guard]>;
- unsafe fn lock(&'a self) -> Self::Output {
- let mut first_idx = 0;
- if self.is_empty() {
- return Box::new([]);
- }
-
- 'outer: loop {
- let mut outputs = Vec::with_capacity(self.len());
-
- outputs.push(self[first_idx].lock());
- for (idx, lock) in self.iter().enumerate() {
- if first_idx == idx {
- continue;
- }
-
- match lock.try_lock() {
- Some(guard) => {
- outputs.push(guard);
- }
- None => {
- first_idx = idx;
- continue 'outer;
- }
- };
- }
-
- return outputs.into_boxed_slice();
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
+ for lock in self.iter() {
+ lock.get_ptrs(ptrs);
}
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- let mut outputs = Vec::with_capacity(self.len());
- for lock in &**self {
- match lock.try_lock() {
- Some(guard) => {
- outputs.push(guard);
- }
- None => return None,
- };
+ unsafe fn guard(&'a self) -> Self::Guard {
+ let mut guards = Vec::new();
+ for lock in self.iter() {
+ guards.push(lock.guard());
}
- Some(outputs.into_boxed_slice())
+ guards.into_boxed_slice()
}
}
unsafe impl<'a, T: Lockable<'a>> Lockable<'a> for Vec<T> {
- type Output = Vec<T::Output>;
+ type Guard = Vec<T::Guard>;
- fn get_ptrs(&self) -> Vec<usize> {
- let mut ptrs = Vec::with_capacity(self.len());
+ fn get_ptrs(&'a self, ptrs: &mut Vec<&'a dyn Lock>) {
for lock in self {
- ptrs.append(&mut lock.get_ptrs());
- }
- ptrs
- }
-
- unsafe fn lock(&'a self) -> Self::Output {
- let mut first_idx = 0;
- if self.is_empty() {
- return Vec::new();
- }
-
- 'outer: loop {
- let mut outputs = Vec::with_capacity(self.len());
-
- outputs.push(self[first_idx].lock());
- for (idx, lock) in self.iter().enumerate() {
- if first_idx == idx {
- continue;
- }
-
- match lock.try_lock() {
- Some(guard) => {
- outputs.push(guard);
- }
- None => {
- first_idx = idx;
- continue 'outer;
- }
- };
- }
-
- return outputs;
+ lock.get_ptrs(ptrs);
}
}
- unsafe fn try_lock(&'a self) -> Option<Self::Output> {
- let mut outputs = Vec::with_capacity(self.len());
+ unsafe fn guard(&'a self) -> Self::Guard {
+ let mut guards = Vec::new();
for lock in self {
- match lock.try_lock() {
- Some(guard) => {
- outputs.push(guard);
- }
- None => return None,
- };
+ guards.push(lock.guard());
}
- Some(outputs)
+ guards
}
}