diff options
Diffstat (limited to 'src/lockable.rs')
| -rw-r--r-- | src/lockable.rs | 706 |
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 } } |
