1 //! Locks that have the same behaviour as a mutex. 2 //! 3 //! The [`Mutex`] in the root of the crate, can be configured using the `ticket_mutex` feature. 4 //! If it's enabled, [`TicketMutex`] and [`TicketMutexGuard`] will be re-exported as [`Mutex`] 5 //! and [`MutexGuard`], otherwise the [`SpinMutex`] and guard will be re-exported. 6 //! 7 //! `ticket_mutex` is disabled by default. 8 //! 9 //! [`Mutex`]: ../struct.Mutex.html 10 //! [`MutexGuard`]: ../struct.MutexGuard.html 11 //! [`TicketMutex`]: ./struct.TicketMutex.html 12 //! [`TicketMutexGuard`]: ./struct.TicketMutexGuard.html 13 //! [`SpinMutex`]: ./struct.SpinMutex.html 14 //! [`SpinMutexGuard`]: ./struct.SpinMutexGuard.html 15 16 #[cfg(feature = "spin_mutex")] 17 #[cfg_attr(docsrs, doc(cfg(feature = "spin_mutex")))] 18 pub mod spin; 19 #[cfg(feature = "spin_mutex")] 20 #[cfg_attr(docsrs, doc(cfg(feature = "spin_mutex")))] 21 pub use self::spin::{SpinMutex, SpinMutexGuard}; 22 23 #[cfg(feature = "ticket_mutex")] 24 #[cfg_attr(docsrs, doc(cfg(feature = "ticket_mutex")))] 25 pub mod ticket; 26 #[cfg(feature = "ticket_mutex")] 27 #[cfg_attr(docsrs, doc(cfg(feature = "ticket_mutex")))] 28 pub use self::ticket::{TicketMutex, TicketMutexGuard}; 29 30 use core::{ 31 fmt, 32 ops::{Deref, DerefMut}, 33 }; 34 use crate::{RelaxStrategy, Spin}; 35 36 #[cfg(all(not(feature = "spin_mutex"), not(feature = "use_ticket_mutex")))] 37 compile_error!("The `mutex` feature flag was used (perhaps through another feature?) without either `spin_mutex` or `use_ticket_mutex`. One of these is required."); 38 39 #[cfg(all(not(feature = "use_ticket_mutex"), feature = "spin_mutex"))] 40 type InnerMutex<T, R> = self::spin::SpinMutex<T, R>; 41 #[cfg(all(not(feature = "use_ticket_mutex"), feature = "spin_mutex"))] 42 type InnerMutexGuard<'a, T> = self::spin::SpinMutexGuard<'a, T>; 43 44 #[cfg(feature = "use_ticket_mutex")] 45 type InnerMutex<T, R> = self::ticket::TicketMutex<T, R>; 46 #[cfg(feature = "use_ticket_mutex")] 47 type InnerMutexGuard<'a, T> = self::ticket::TicketMutexGuard<'a, T>; 48 49 /// A spin-based lock providing mutually exclusive access to data. 50 /// 51 /// The implementation uses either a ticket mutex or a regular spin mutex depending on whether the `spin_mutex` or 52 /// `ticket_mutex` feature flag is enabled. 53 /// 54 /// # Example 55 /// 56 /// ``` 57 /// use spin; 58 /// 59 /// let lock = spin::Mutex::new(0); 60 /// 61 /// // Modify the data 62 /// *lock.lock() = 2; 63 /// 64 /// // Read the data 65 /// let answer = *lock.lock(); 66 /// assert_eq!(answer, 2); 67 /// ``` 68 /// 69 /// # Thread safety example 70 /// 71 /// ``` 72 /// use spin; 73 /// use std::sync::{Arc, Barrier}; 74 /// 75 /// let thread_count = 1000; 76 /// let spin_mutex = Arc::new(spin::Mutex::new(0)); 77 /// 78 /// // We use a barrier to ensure the readout happens after all writing 79 /// let barrier = Arc::new(Barrier::new(thread_count + 1)); 80 /// 81 /// for _ in (0..thread_count) { 82 /// let my_barrier = barrier.clone(); 83 /// let my_lock = spin_mutex.clone(); 84 /// std::thread::spawn(move || { 85 /// let mut guard = my_lock.lock(); 86 /// *guard += 1; 87 /// 88 /// // Release the lock to prevent a deadlock 89 /// drop(guard); 90 /// my_barrier.wait(); 91 /// }); 92 /// } 93 /// 94 /// barrier.wait(); 95 /// 96 /// let answer = { *spin_mutex.lock() }; 97 /// assert_eq!(answer, thread_count); 98 /// ``` 99 pub struct Mutex<T: ?Sized, R = Spin> { 100 inner: InnerMutex<T, R>, 101 } 102 103 unsafe impl<T: ?Sized + Send, R> Sync for Mutex<T, R> {} 104 unsafe impl<T: ?Sized + Send, R> Send for Mutex<T, R> {} 105 106 /// A generic guard that will protect some data access and 107 /// uses either a ticket lock or a normal spin mutex. 108 /// 109 /// For more info see [`TicketMutexGuard`] or [`SpinMutexGuard`]. 110 /// 111 /// [`TicketMutexGuard`]: ./struct.TicketMutexGuard.html 112 /// [`SpinMutexGuard`]: ./struct.SpinMutexGuard.html 113 pub struct MutexGuard<'a, T: 'a + ?Sized> { 114 inner: InnerMutexGuard<'a, T>, 115 } 116 117 impl<T, R> Mutex<T, R> { 118 /// Creates a new [`Mutex`] wrapping the supplied data. 119 /// 120 /// # Example 121 /// 122 /// ``` 123 /// use spin::Mutex; 124 /// 125 /// static MUTEX: Mutex<()> = Mutex::new(()); 126 /// 127 /// fn demo() { 128 /// let lock = MUTEX.lock(); 129 /// // do something with lock 130 /// drop(lock); 131 /// } 132 /// ``` 133 #[inline(always)] new(value: T) -> Self134 pub const fn new(value: T) -> Self { 135 Self { inner: InnerMutex::new(value) } 136 } 137 138 /// Consumes this [`Mutex`] and unwraps the underlying data. 139 /// 140 /// # Example 141 /// 142 /// ``` 143 /// let lock = spin::Mutex::new(42); 144 /// assert_eq!(42, lock.into_inner()); 145 /// ``` 146 #[inline(always)] into_inner(self) -> T147 pub fn into_inner(self) -> T { 148 self.inner.into_inner() 149 } 150 } 151 152 impl<T: ?Sized, R: RelaxStrategy> Mutex<T, R> { 153 /// Locks the [`Mutex`] and returns a guard that permits access to the inner data. 154 /// 155 /// The returned value may be dereferenced for data access 156 /// and the lock will be dropped when the guard falls out of scope. 157 /// 158 /// ``` 159 /// let lock = spin::Mutex::new(0); 160 /// { 161 /// let mut data = lock.lock(); 162 /// // The lock is now locked and the data can be accessed 163 /// *data += 1; 164 /// // The lock is implicitly dropped at the end of the scope 165 /// } 166 /// ``` 167 #[inline(always)] lock(&self) -> MutexGuard<T>168 pub fn lock(&self) -> MutexGuard<T> { 169 MutexGuard { 170 inner: self.inner.lock(), 171 } 172 } 173 } 174 175 impl<T: ?Sized, R> Mutex<T, R> { 176 /// Returns `true` if the lock is currently held. 177 /// 178 /// # Safety 179 /// 180 /// This function provides no synchronization guarantees and so its result should be considered 'out of date' 181 /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic. 182 #[inline(always)] is_locked(&self) -> bool183 pub fn is_locked(&self) -> bool { 184 self.inner.is_locked() 185 } 186 187 /// Force unlock this [`Mutex`]. 188 /// 189 /// # Safety 190 /// 191 /// This is *extremely* unsafe if the lock is not held by the current 192 /// thread. However, this can be useful in some instances for exposing the 193 /// lock to FFI that doesn't know how to deal with RAII. 194 #[inline(always)] force_unlock(&self)195 pub unsafe fn force_unlock(&self) { 196 self.inner.force_unlock() 197 } 198 199 /// Try to lock this [`Mutex`], returning a lock guard if successful. 200 /// 201 /// # Example 202 /// 203 /// ``` 204 /// let lock = spin::Mutex::new(42); 205 /// 206 /// let maybe_guard = lock.try_lock(); 207 /// assert!(maybe_guard.is_some()); 208 /// 209 /// // `maybe_guard` is still held, so the second call fails 210 /// let maybe_guard2 = lock.try_lock(); 211 /// assert!(maybe_guard2.is_none()); 212 /// ``` 213 #[inline(always)] try_lock(&self) -> Option<MutexGuard<T>>214 pub fn try_lock(&self) -> Option<MutexGuard<T>> { 215 self.inner 216 .try_lock() 217 .map(|guard| MutexGuard { inner: guard }) 218 } 219 220 /// Returns a mutable reference to the underlying data. 221 /// 222 /// Since this call borrows the [`Mutex`] mutably, and a mutable reference is guaranteed to be exclusive in Rust, 223 /// no actual locking needs to take place -- the mutable borrow statically guarantees no locks exist. As such, 224 /// this is a 'zero-cost' operation. 225 /// 226 /// # Example 227 /// 228 /// ``` 229 /// let mut lock = spin::Mutex::new(0); 230 /// *lock.get_mut() = 10; 231 /// assert_eq!(*lock.lock(), 10); 232 /// ``` 233 #[inline(always)] get_mut(&mut self) -> &mut T234 pub fn get_mut(&mut self) -> &mut T { 235 self.inner.get_mut() 236 } 237 } 238 239 impl<T: ?Sized + fmt::Debug, R> fmt::Debug for Mutex<T, R> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result240 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 241 fmt::Debug::fmt(&self.inner, f) 242 } 243 } 244 245 impl<T: ?Sized + Default, R> Default for Mutex<T, R> { default() -> Self246 fn default() -> Self { 247 Self::new(Default::default()) 248 } 249 } 250 251 impl<T, R> From<T> for Mutex<T, R> { from(data: T) -> Self252 fn from(data: T) -> Self { 253 Self::new(data) 254 } 255 } 256 257 impl<'a, T: ?Sized> MutexGuard<'a, T> { 258 /// Leak the lock guard, yielding a mutable reference to the underlying data. 259 /// 260 /// Note that this function will permanently lock the original [`Mutex`]. 261 /// 262 /// ``` 263 /// let mylock = spin::Mutex::new(0); 264 /// 265 /// let data: &mut i32 = spin::MutexGuard::leak(mylock.lock()); 266 /// 267 /// *data = 1; 268 /// assert_eq!(*data, 1); 269 /// ``` 270 #[inline(always)] leak(this: Self) -> &'a mut T271 pub fn leak(this: Self) -> &'a mut T { 272 InnerMutexGuard::leak(this.inner) 273 } 274 } 275 276 impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result277 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 278 fmt::Debug::fmt(&**self, f) 279 } 280 } 281 282 impl<'a, T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'a, T> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result283 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 284 fmt::Display::fmt(&**self, f) 285 } 286 } 287 288 impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> { 289 type Target = T; deref(&self) -> &T290 fn deref(&self) -> &T { 291 &*self.inner 292 } 293 } 294 295 impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> { deref_mut(&mut self) -> &mut T296 fn deref_mut(&mut self) -> &mut T { 297 &mut *self.inner 298 } 299 } 300 301 #[cfg(feature = "lock_api")] 302 unsafe impl<R: RelaxStrategy> lock_api_crate::RawMutex for Mutex<(), R> { 303 type GuardMarker = lock_api_crate::GuardSend; 304 305 const INIT: Self = Self::new(()); 306 lock(&self)307 fn lock(&self) { 308 // Prevent guard destructor running 309 core::mem::forget(Self::lock(self)); 310 } 311 try_lock(&self) -> bool312 fn try_lock(&self) -> bool { 313 // Prevent guard destructor running 314 Self::try_lock(self).map(core::mem::forget).is_some() 315 } 316 unlock(&self)317 unsafe fn unlock(&self) { 318 self.force_unlock(); 319 } 320 is_locked(&self) -> bool321 fn is_locked(&self) -> bool { 322 self.inner.is_locked() 323 } 324 } 325