From fe67aa262f1b04fb6c38683d9221c3a2fafcc35a Mon Sep 17 00:00:00 2001 From: Mica White Date: Sun, 10 Mar 2024 20:21:00 -0400 Subject: Reorganization --- src/mutex.rs | 265 +---------------------------------------------------------- 1 file changed, 4 insertions(+), 261 deletions(-) (limited to 'src/mutex.rs') diff --git a/src/mutex.rs b/src/mutex.rs index 0d67f33..db0147f 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -1,12 +1,14 @@ use std::cell::UnsafeCell; -use std::fmt::Debug; use std::marker::PhantomData; -use std::ops::{Deref, DerefMut}; use lock_api::RawMutex; use crate::key::Keyable; +mod guard; +mod mutex; +mod mutex_ref; + /// A spinning mutex #[cfg(feature = "spin")] pub type SpinLock = Mutex>; @@ -38,34 +40,6 @@ pub struct Mutex { /// A reference to a mutex that unlocks it when dropped pub struct MutexRef<'a, T: ?Sized + 'a, R: RawMutex>(&'a Mutex); -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() } - } -} - -impl<'a, T: ?Sized + 'a, R: RawMutex> Deref for MutexRef<'a, T, R> { - type Target = T; - - fn deref(&self) -> &Self::Target { - // safety: this is the only type that can use `value`, and there's - // a reference to this type, so there cannot be any mutable - // references to this value. - unsafe { &*self.0.value.get() } - } -} - -impl<'a, T: ?Sized + 'a, R: RawMutex> DerefMut for MutexRef<'a, T, R> { - fn deref_mut(&mut self) -> &mut Self::Target { - // safety: this is the only type that can use `value`, and we have a - // mutable reference to this type, so there cannot be any other - // references to this value. - unsafe { &mut *self.0.value.get() } - } -} - /// An RAII implementation of a “scoped lock” of a mutex. When this structure /// is dropped (falls out of scope), the lock will be unlocked. /// @@ -78,234 +52,3 @@ pub struct MutexGuard<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable + 'key, R: RawM thread_key: Key, _phantom: PhantomData<&'key ()>, } - -impl<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> Deref - for MutexGuard<'a, 'key, T, Key, R> -{ - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.mutex - } -} - -impl<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> DerefMut - for MutexGuard<'a, 'key, T, Key, R> -{ - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.mutex - } -} - -impl<'a, 'key: 'a, T: ?Sized + 'a, Key: Keyable, R: RawMutex> MutexGuard<'a, 'key, T, Key, R> { - /// Create a guard to the given mutex. Undefined if multiple guards to the - /// same mutex exist at once. - #[must_use] - const unsafe fn new(mutex: &'a Mutex, thread_key: Key) -> Self { - Self { - mutex: MutexRef(mutex), - thread_key, - _phantom: PhantomData, - } - } -} - -impl Mutex { - /// Create a new unlocked `Mutex`. - /// - /// # Examples - /// - /// ``` - /// use happylock::Mutex; - /// - /// let mutex = Mutex::new(0); - /// ``` - #[must_use] - pub const fn new(value: T) -> Self { - Self { - raw: R::INIT, - value: UnsafeCell::new(value), - } - } -} - -impl Debug for Mutex { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(&format!("Mutex<{}>", std::any::type_name::())) - } -} - -impl From for Mutex { - fn from(value: T) -> Self { - Self::new(value) - } -} - -impl AsMut for Mutex { - fn as_mut(&mut self) -> &mut T { - self.get_mut() - } -} - -impl Mutex { - /// Consumes this mutex, returning the underlying data. - /// - /// # Examples - /// - /// ``` - /// use happylock::Mutex; - /// - /// let mutex = Mutex::new(0); - /// assert_eq!(mutex.into_inner(), 0); - /// ``` - #[must_use] - pub fn into_inner(self) -> T { - self.value.into_inner() - } -} - -impl Mutex { - /// Returns a mutable reference to the underlying data. - /// - /// Since this call borrows `Mutex` mutably, no actual locking is taking - /// place. The mutable borrow statically guarantees that no locks exist. - /// - /// # Examples - /// - /// ``` - /// use happylock::{ThreadKey, Mutex}; - /// - /// let key = ThreadKey::lock().unwrap(); - /// let mut mutex = Mutex::new(0); - /// *mutex.get_mut() = 10; - /// assert_eq!(*mutex.lock(key), 10); - /// ``` - #[must_use] - pub fn get_mut(&mut self) -> &mut T { - self.value.get_mut() - } -} - -impl Mutex { - /// Block the thread until this mutex can be locked, and lock it. - /// - /// Upon returning, the thread is the only thread with a lock on the - /// `Mutex`. A [`MutexGuard`] is returned to allow a scoped unlock of this - /// `Mutex`. When the guard is dropped, this `Mutex` will unlock. - /// - /// # Examples - /// - /// ``` - /// use std::{thread, sync::Arc}; - /// use happylock::{Mutex, ThreadKey}; - /// - /// let mutex = Arc::new(Mutex::new(0)); - /// let c_mutex = Arc::clone(&mutex); - /// - /// thread::spawn(move || { - /// let key = ThreadKey::lock().unwrap(); - /// *c_mutex.lock(key) = 10; - /// }).join().expect("thread::spawn failed"); - /// - /// let key = ThreadKey::lock().unwrap(); - /// assert_eq!(*mutex.lock(key), 10); - /// ``` - pub fn lock<'s, 'k: 's, Key: Keyable>(&'s self, key: Key) -> MutexGuard<'_, 'k, T, Key, R> { - unsafe { - self.raw.lock(); - - // safety: we just locked the mutex - MutexGuard::new(self, key) - } - } - - /// Lock without a [`ThreadKey`]. You must exclusively own the - /// [`ThreadKey`] as long as the [`MutexRef`] is alive. This may cause - /// deadlock if called multiple times without unlocking first. - pub(crate) unsafe fn lock_no_key(&self) -> MutexRef<'_, T, R> { - self.raw.lock(); - - MutexRef(self) - } - - /// Attempts to lock the `Mutex` without blocking. - /// - /// # Errors - /// - /// Returns [`Err`] if the `Mutex` cannot be locked without blocking. - /// - /// # Examples - /// - /// ``` - /// use std::{thread, sync::Arc}; - /// use happylock::{Mutex, ThreadKey}; - /// - /// let mutex = Arc::new(Mutex::new(0)); - /// let c_mutex = Arc::clone(&mutex); - /// - /// thread::spawn(move || { - /// let key = ThreadKey::lock().unwrap(); - /// let mut lock = c_mutex.try_lock(key); - /// if let Some(mut lock) = lock { - /// *lock = 10; - /// } else { - /// println!("try_lock failed"); - /// } - /// }).join().expect("thread::spawn failed"); - /// - /// let key = ThreadKey::lock().unwrap(); - /// assert_eq!(*mutex.lock(key), 10); - /// ``` - pub fn try_lock<'s, 'a: 's, 'k: 'a, Key: Keyable>( - &'s self, - key: Key, - ) -> Option> { - if self.raw.try_lock() { - // safety: we just locked the mutex - Some(unsafe { MutexGuard::new(self, key) }) - } else { - None - } - } - - /// 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> { - self.raw.try_lock().then_some(MutexRef(self)) - } - - /// 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. - unsafe fn force_unlock(&self) { - self.raw.unlock(); - } - - /// Consumes the [`MutexGuard`], and consequently unlocks its `Mutex`. - /// - /// # Examples - /// - /// ``` - /// use happylock::{ThreadKey, Mutex}; - /// - /// let key = ThreadKey::lock().unwrap(); - /// let mutex = Mutex::new(0); - /// - /// let mut guard = mutex.lock(key); - /// *guard += 20; - /// - /// let key = Mutex::unlock(guard); - /// ``` - pub fn unlock<'a, 'k: 'a, Key: Keyable + 'k>(guard: MutexGuard<'a, 'k, T, Key, R>) -> Key { - unsafe { - guard.mutex.0.force_unlock(); - } - guard.thread_key - } -} - -unsafe impl Send for Mutex {} -unsafe impl Sync for Mutex {} -- cgit v1.2.3