From 56c6999e79dbc48f14ee5fb322828f79fc478d15 Mon Sep 17 00:00:00 2001 From: Mica White Date: Thu, 7 Mar 2024 11:23:10 -0500 Subject: reorganization --- src/guard.rs | 171 +---------------------------------------------------------- 1 file changed, 2 insertions(+), 169 deletions(-) (limited to 'src/guard.rs') diff --git a/src/guard.rs b/src/guard.rs index 6007ebe..9758e63 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -1,173 +1,6 @@ -use std::{ - mem::MaybeUninit, - ops::{Deref, DerefMut}, -}; +use std::ops::{Deref, DerefMut}; -use crate::{ - mutex::{Mutex, MutexRef, RawMutex}, - ThreadKey, -}; - -mod sealed { - #[allow(clippy::wildcard_imports)] - use super::*; - pub trait Sealed {} - impl<'a, T, R: RawMutex + 'a> Sealed for Mutex {} - impl Sealed for &T {} - impl Sealed for &mut T {} - impl<'a, A: Lockable<'a>, B: Lockable<'a>> Sealed for (A, B) {} - impl<'a, T: Lockable<'a>, const N: usize> Sealed for [T; N] {} -} - -pub trait Lockable<'a>: sealed::Sealed { - /// The output of the lock - type Output; - - /// Blocks until the lock is acquired - /// - /// # Safety - /// - /// It is undefined behavior to: - /// * Use this without ownership of the [`ThreadKey`], which should last as - /// long as the return value is alive. - /// * Call this on multiple locks without unlocking first. - unsafe fn lock(&'a self) -> Self::Output; - - /// Attempt to lock without blocking. - /// - /// Returns `Ok` if successful, `None` otherwise. - /// - /// # Safety - /// - /// It is undefined behavior to use this without ownership of the - /// [`ThreadKey`], which should last as long as the return value is alive. - unsafe fn try_lock(&'a self) -> Option; - - /// Release the lock - fn unlock(guard: Self::Output); -} - -impl<'a, T: Lockable<'a>> Lockable<'a> for &T { - type Output = T::Output; - - unsafe fn lock(&'a self) -> Self::Output { - (*self).lock() - } - - unsafe fn try_lock(&'a self) -> Option { - (*self).try_lock() - } - - #[allow(clippy::semicolon_if_nothing_returned)] - fn unlock(guard: Self::Output) { - T::unlock(guard) - } -} - -impl<'a, T: Lockable<'a>> Lockable<'a> for &mut T { - type Output = T::Output; - - unsafe fn lock(&'a self) -> Self::Output { - (**self).lock() - } - - unsafe fn try_lock(&'a self) -> Option { - (**self).try_lock() - } - - #[allow(clippy::semicolon_if_nothing_returned)] - fn unlock(guard: Self::Output) { - T::unlock(guard) - } -} - -impl<'a, T: 'a, R: RawMutex + 'a> Lockable<'a> for Mutex { - type Output = MutexRef<'a, T, R>; - - unsafe fn lock(&'a self) -> Self::Output { - self.lock_ref() - } - - unsafe fn try_lock(&'a self) -> Option { - self.try_lock_ref() - } - - fn unlock(guard: Self::Output) { - drop(guard); - } -} - -impl<'a, A: Lockable<'a>, B: Lockable<'a>> Lockable<'a> for (A, B) { - type Output = (A::Output, B::Output); - - unsafe fn lock(&'a self) -> Self::Output { - loop { - let lock1 = self.0.lock(); - match self.1.try_lock() { - Some(lock2) => return (lock1, lock2), - None => A::unlock(lock1), - } - } - } - - unsafe fn try_lock(&'a self) -> Option { - self.0.try_lock().and_then(|guard1| { - if let Some(guard2) = self.1.try_lock() { - Some((guard1, guard2)) - } else { - A::unlock(guard1); - None - } - }) - } - - fn unlock(guard: Self::Output) { - A::unlock(guard.0); - B::unlock(guard.1); - } -} - -impl<'a, T: Lockable<'a>, const N: usize> Lockable<'a> for [T; N] { - type Output = [T::Output; N]; - - unsafe fn lock(&'a self) -> Self::Output { - loop { - if let Some(guard) = self.try_lock() { - return guard; - } - } - } - - unsafe fn try_lock(&'a self) -> Option { - unsafe fn unlock_partial<'a, T: Lockable<'a>, const N: usize>( - guards: [MaybeUninit; N], - upto: usize, - ) { - for (i, guard) in guards.into_iter().enumerate() { - if i == upto { - break; - } - T::unlock(guard.assume_init()); - } - } - - let mut outputs = MaybeUninit::<[MaybeUninit; N]>::uninit().assume_init(); - for i in 0..N { - if let Some(guard) = self[i].try_lock() { - outputs[i].write(guard) - } else { - unlock_partial::(outputs, i); - return None; - }; - } - - Some(outputs.map(|mu| mu.assume_init())) - } - - fn unlock(guard: Self::Output) { - guard.map(T::unlock); - } -} +use crate::{lockable::Lockable, ThreadKey}; pub struct LockGuard<'a, L: Lockable<'a>> { guard: L::Output, -- cgit v1.2.3