use core::cell::UnsafeCell; use core::default::Default; use core::fmt; use core::hint; use core::marker::Sync; use core::ops::{Deref, DerefMut, Drop}; use core::option::Option::{self, None, Some}; use core::sync::atomic::{AtomicBool, Ordering}; /// This type provides MUTual EXclusion based on spinning. pub(crate) struct Mutex { lock: AtomicBool, data: UnsafeCell, } /// A guard to which the protected data can be accessed /// /// When the guard falls out of scope it will release the lock. #[derive(Debug)] pub(crate) struct MutexGuard<'a, T: ?Sized> { lock: &'a AtomicBool, data: &'a mut T, } // Same unsafe impls as `std::sync::Mutex` unsafe impl Sync for Mutex {} unsafe impl Send for Mutex {} impl Mutex { /// Creates a new spinlock wrapping the supplied data. pub(crate) const fn new(user_data: T) -> Mutex { Mutex { lock: AtomicBool::new(false), data: UnsafeCell::new(user_data), } } } impl Mutex { fn obtain_lock(&self) { while self .lock .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed) .is_err() { // Wait until the lock looks unlocked before retrying while self.lock.load(Ordering::Relaxed) { hint::spin_loop(); } } } /// Locks the spinlock and returns a guard. /// /// The returned value may be dereferenced for data access /// and the lock will be dropped when the guard falls out of scope. pub(crate) fn lock(&self) -> MutexGuard<'_, T> { self.obtain_lock(); MutexGuard { lock: &self.lock, data: unsafe { &mut *self.data.get() }, } } /// Tries to lock the mutex. If it is already locked, it will return None. Otherwise it returns /// a guard within Some. pub(crate) fn try_lock(&self) -> Option> { if self .lock .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) .is_ok() { Some(MutexGuard { lock: &self.lock, data: unsafe { &mut *self.data.get() }, }) } else { None } } } impl fmt::Debug for Mutex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_lock() { Some(guard) => write!(f, "Mutex {{ data: ") .and_then(|()| (&*guard).fmt(f)) .and_then(|()| write!(f, "}}")), None => write!(f, "Mutex {{ }}"), } } } impl Default for Mutex { fn default() -> Mutex { Mutex::new(Default::default()) } } impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> { type Target = T; fn deref<'b>(&'b self) -> &'b T { &*self.data } } impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> { fn deref_mut<'b>(&'b mut self) -> &'b mut T { &mut *self.data } } impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { /// The dropping of the MutexGuard will release the lock it was created from. fn drop(&mut self) { self.lock.store(false, Ordering::Release); } }