1 use core::cell::UnsafeCell; 2 use core::default::Default; 3 use core::fmt; 4 use core::hint; 5 use core::marker::Sync; 6 use core::ops::{Deref, DerefMut, Drop}; 7 use core::option::Option::{self, None, Some}; 8 use core::sync::atomic::{AtomicBool, Ordering}; 9 10 /// This type provides MUTual EXclusion based on spinning. 11 pub(crate) struct Mutex<T: ?Sized> { 12 lock: AtomicBool, 13 data: UnsafeCell<T>, 14 } 15 16 /// A guard to which the protected data can be accessed 17 /// 18 /// When the guard falls out of scope it will release the lock. 19 #[derive(Debug)] 20 pub(crate) struct MutexGuard<'a, T: ?Sized> { 21 lock: &'a AtomicBool, 22 data: &'a mut T, 23 } 24 25 // Same unsafe impls as `std::sync::Mutex` 26 unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {} 27 unsafe impl<T: ?Sized + Send> Send for Mutex<T> {} 28 29 impl<T> Mutex<T> { 30 /// Creates a new spinlock wrapping the supplied data. new(user_data: T) -> Mutex<T>31 pub(crate) const fn new(user_data: T) -> Mutex<T> { 32 Mutex { 33 lock: AtomicBool::new(false), 34 data: UnsafeCell::new(user_data), 35 } 36 } 37 } 38 39 impl<T: ?Sized> Mutex<T> { obtain_lock(&self)40 fn obtain_lock(&self) { 41 while self 42 .lock 43 .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed) 44 .is_err() 45 { 46 // Wait until the lock looks unlocked before retrying 47 while self.lock.load(Ordering::Relaxed) { 48 hint::spin_loop(); 49 } 50 } 51 } 52 53 /// Locks the spinlock and returns a guard. 54 /// 55 /// The returned value may be dereferenced for data access 56 /// and the lock will be dropped when the guard falls out of scope. lock(&self) -> MutexGuard<'_, T>57 pub(crate) fn lock(&self) -> MutexGuard<'_, T> { 58 self.obtain_lock(); 59 MutexGuard { 60 lock: &self.lock, 61 data: unsafe { &mut *self.data.get() }, 62 } 63 } 64 65 /// Tries to lock the mutex. If it is already locked, it will return None. Otherwise it returns 66 /// a guard within Some. try_lock(&self) -> Option<MutexGuard<'_, T>>67 pub(crate) fn try_lock(&self) -> Option<MutexGuard<'_, T>> { 68 if self 69 .lock 70 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) 71 .is_ok() 72 { 73 Some(MutexGuard { 74 lock: &self.lock, 75 data: unsafe { &mut *self.data.get() }, 76 }) 77 } else { 78 None 79 } 80 } 81 } 82 83 impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 85 match self.try_lock() { 86 Some(guard) => write!(f, "Mutex {{ data: ") 87 .and_then(|()| (&*guard).fmt(f)) 88 .and_then(|()| write!(f, "}}")), 89 None => write!(f, "Mutex {{ <locked> }}"), 90 } 91 } 92 } 93 94 impl<T: ?Sized + Default> Default for Mutex<T> { default() -> Mutex<T>95 fn default() -> Mutex<T> { 96 Mutex::new(Default::default()) 97 } 98 } 99 100 impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> { 101 type Target = T; deref<'b>(&'b self) -> &'b T102 fn deref<'b>(&'b self) -> &'b T { 103 &*self.data 104 } 105 } 106 107 impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> { deref_mut<'b>(&'b mut self) -> &'b mut T108 fn deref_mut<'b>(&'b mut self) -> &'b mut T { 109 &mut *self.data 110 } 111 } 112 113 impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { 114 /// The dropping of the MutexGuard will release the lock it was created from. drop(&mut self)115 fn drop(&mut self) { 116 self.lock.store(false, Ordering::Release); 117 } 118 } 119