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