• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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