Skip to main content

spin/
mutex.rs

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`]: ./ticket/struct.TicketMutex.html
12//! [`TicketMutexGuard`]: ./ticket/struct.TicketMutexGuard.html
13//! [`SpinMutex`]: ./spin/struct.SpinMutex.html
14//! [`SpinMutexGuard`]: ./spin/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, R> = self::spin::SpinMutexGuard<'a, T, R>;
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, R> = self::ticket::TicketMutexGuard<'a, T, R>;
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
117/// A generic guard that will protect some data access and
118/// uses either a ticket lock or a normal spin mutex.
119///
120/// For more info see [`TicketMutexGuard`] or [`SpinMutexGuard`].
121///
122/// [`TicketMutexGuard`]: ./struct.TicketMutexGuard.html
123/// [`SpinMutexGuard`]: ./struct.SpinMutexGuard.html
124pub struct MutexGuard<'a, T: 'a + ?Sized, R> {
125    inner: InnerMutexGuard<'a, T, R>,
126}
127
128// SAFETY: Same unsafe impls as `std::sync::Mutex`
129unsafe impl<T: ?Sized + Send, R> Sync for Mutex<T, R> {}
130unsafe impl<T: ?Sized + Send, R> Send for Mutex<T, R> {}
131
132// SAFETY: Mutex guards can be thought of as mutable reference to the inner data. In fact, this
133// would be their ideal representation if it were not for the need for the critical section to end
134// *after* the reference is no longer live.
135unsafe impl<T: ?Sized, R> Sync for MutexGuard<'_, T, R> where for<'a> &'a mut T: Sync {}
136unsafe impl<T: ?Sized, R> Send for MutexGuard<'_, T, R> where for<'a> &'a mut T: Send {}
137
138impl<T, R> Mutex<T, R> {
139    /// Creates a new [`Mutex`] wrapping the supplied data.
140    ///
141    /// # Example
142    ///
143    /// ```
144    /// use spin::Mutex;
145    ///
146    /// static MUTEX: Mutex<()> = Mutex::new(());
147    ///
148    /// fn demo() {
149    ///     let lock = MUTEX.lock();
150    ///     // do something with lock
151    ///     drop(lock);
152    /// }
153    /// ```
154    #[inline(always)]
155    pub const fn new(value: T) -> Self {
156        Self {
157            inner: InnerMutex::new(value),
158        }
159    }
160
161    /// Consumes this [`Mutex`] and unwraps the underlying data.
162    ///
163    /// # Example
164    ///
165    /// ```
166    /// let lock = spin::Mutex::new(42);
167    /// assert_eq!(42, lock.into_inner());
168    /// ```
169    #[inline(always)]
170    pub fn into_inner(self) -> T {
171        self.inner.into_inner()
172    }
173}
174
175impl<T: ?Sized, R: RelaxStrategy> Mutex<T, R> {
176    /// Locks the [`Mutex`] and returns a guard that permits access to the inner data.
177    ///
178    /// The returned value may be dereferenced for data access
179    /// and the lock will be dropped when the guard falls out of scope.
180    ///
181    /// ```
182    /// let lock = spin::Mutex::new(0);
183    /// {
184    ///     let mut data = lock.lock();
185    ///     // The lock is now locked and the data can be accessed
186    ///     *data += 1;
187    ///     // The lock is implicitly dropped at the end of the scope
188    /// }
189    /// ```
190    #[inline(always)]
191    pub fn lock(&self) -> MutexGuard<'_, T, R> {
192        MutexGuard {
193            inner: self.inner.lock(),
194        }
195    }
196}
197
198impl<T: ?Sized, R> Mutex<T, R> {
199    /// Returns `true` if the lock is currently held.
200    ///
201    /// # Safety
202    ///
203    /// This function provides no synchronization guarantees and so its result should be considered 'out of date'
204    /// the instant it is called. Do not use it for synchronization purposes. However, it may be useful as a heuristic.
205    #[inline(always)]
206    pub fn is_locked(&self) -> bool {
207        self.inner.is_locked()
208    }
209
210    /// Force unlock this [`Mutex`].
211    ///
212    /// # Safety
213    ///
214    /// This is *extremely* unsafe if the lock is not held by the current
215    /// thread. However, this can be useful in some instances for exposing the
216    /// lock to FFI that doesn't know how to deal with RAII.
217    #[inline(always)]
218    pub unsafe fn force_unlock(&self) {
219        self.inner.force_unlock()
220    }
221
222    /// Try to lock this [`Mutex`], returning a lock guard if successful.
223    ///
224    /// # Example
225    ///
226    /// ```
227    /// let lock = spin::Mutex::new(42);
228    ///
229    /// let maybe_guard = lock.try_lock();
230    /// assert!(maybe_guard.is_some());
231    ///
232    /// // `maybe_guard` is still held, so the second call fails
233    /// let maybe_guard2 = lock.try_lock();
234    /// assert!(maybe_guard2.is_none());
235    /// ```
236    #[inline(always)]
237    pub fn try_lock(&self) -> Option<MutexGuard<'_, T, R>> {
238        self.inner
239            .try_lock()
240            .map(|guard| MutexGuard { inner: guard })
241    }
242
243    /// Returns a mutable reference to the underlying data.
244    ///
245    /// Since this call borrows the [`Mutex`] mutably, and a mutable reference is guaranteed to be exclusive in Rust,
246    /// no actual locking needs to take place -- the mutable borrow statically guarantees no locks exist. As such,
247    /// this is a 'zero-cost' operation.
248    ///
249    /// # Example
250    ///
251    /// ```
252    /// let mut lock = spin::Mutex::new(0);
253    /// *lock.get_mut() = 10;
254    /// assert_eq!(*lock.lock(), 10);
255    /// ```
256    #[inline(always)]
257    pub fn get_mut(&mut self) -> &mut T {
258        self.inner.get_mut()
259    }
260}
261
262impl<T: ?Sized + fmt::Debug, R> fmt::Debug for Mutex<T, R> {
263    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
264        fmt::Debug::fmt(&self.inner, f)
265    }
266}
267
268impl<T: Default, R> Default for Mutex<T, R> {
269    fn default() -> Self {
270        Self::new(Default::default())
271    }
272}
273
274impl<T, R> From<T> for Mutex<T, R> {
275    fn from(data: T) -> Self {
276        Self::new(data)
277    }
278}
279
280impl<'a, T: ?Sized, R> MutexGuard<'a, T, R> {
281    /// Leak the lock guard, yielding a mutable reference to the underlying data.
282    ///
283    /// Note that this function will permanently lock the original [`Mutex`].
284    ///
285    /// ```
286    /// let mylock = spin::Mutex::new(0);
287    ///
288    /// let data: &mut i32 = spin::MutexGuard::leak(mylock.lock());
289    ///
290    /// *data = 1;
291    /// assert_eq!(*data, 1);
292    /// ```
293    #[inline(always)]
294    pub fn leak(this: Self) -> &'a mut T {
295        InnerMutexGuard::leak(this.inner)
296    }
297}
298
299impl<'a, T: ?Sized + fmt::Debug, R> fmt::Debug for MutexGuard<'a, T, R> {
300    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
301        fmt::Debug::fmt(&**self, f)
302    }
303}
304
305impl<'a, T: ?Sized + fmt::Display, R> fmt::Display for MutexGuard<'a, T, R> {
306    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
307        fmt::Display::fmt(&**self, f)
308    }
309}
310
311impl<'a, T: ?Sized, R> Deref for MutexGuard<'a, T, R> {
312    type Target = T;
313    fn deref(&self) -> &T {
314        &self.inner
315    }
316}
317
318impl<'a, T: ?Sized, R> DerefMut for MutexGuard<'a, T, R> {
319    fn deref_mut(&mut self) -> &mut T {
320        &mut self.inner
321    }
322}
323
324#[cfg(feature = "lock_api")]
325unsafe impl<R: RelaxStrategy> lock_api_crate::RawMutex for Mutex<(), R> {
326    type GuardMarker = lock_api_crate::GuardSend;
327
328    const INIT: Self = Self::new(());
329
330    fn lock(&self) {
331        // Prevent guard destructor running
332        core::mem::forget(Self::lock(self));
333    }
334
335    fn try_lock(&self) -> bool {
336        // Prevent guard destructor running
337        Self::try_lock(self).map(core::mem::forget).is_some()
338    }
339
340    unsafe fn unlock(&self) {
341        self.force_unlock();
342    }
343
344    fn is_locked(&self) -> bool {
345        self.inner.is_locked()
346    }
347}