Skip to main content

lock_api/
mutex.rs

1// Copyright 2018 Amanieu d'Antras
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use core::cell::UnsafeCell;
9use core::fmt;
10use core::marker::PhantomData;
11use core::mem;
12use core::ops::{Deref, DerefMut};
13
14#[cfg(feature = "arc_lock")]
15use alloc::sync::Arc;
16#[cfg(feature = "arc_lock")]
17use core::mem::ManuallyDrop;
18#[cfg(feature = "arc_lock")]
19use core::ptr;
20
21#[cfg(feature = "owning_ref")]
22use owning_ref::StableAddress;
23
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Deserializer, Serialize, Serializer};
26
27/// Basic operations for a mutex.
28///
29/// Types implementing this trait can be used by `Mutex` to form a safe and
30/// fully-functioning mutex type.
31///
32/// # Safety
33///
34/// Implementations of this trait must ensure that the mutex is actually
35/// exclusive: a lock can't be acquired while the mutex is already locked.
36pub unsafe trait RawMutex {
37    /// Initial value for an unlocked mutex.
38    // A “non-constant” const item is a legacy way to supply an initialized value to downstream
39    // static items. Can hopefully be replaced with `const fn new() -> Self` at some point.
40    #[allow(clippy::declare_interior_mutable_const)]
41    const INIT: Self;
42
43    /// Marker type which determines whether a lock guard should be `Send`. Use
44    /// one of the `GuardSend` or `GuardNoSend` helper types here.
45    type GuardMarker;
46
47    /// Acquires this mutex, blocking the current thread until it is able to do so.
48    fn lock(&self);
49
50    /// Attempts to acquire this mutex without blocking. Returns `true`
51    /// if the lock was successfully acquired and `false` otherwise.
52    fn try_lock(&self) -> bool;
53
54    /// Unlocks this mutex.
55    ///
56    /// # Safety
57    ///
58    /// This method may only be called if the mutex is held in the current context, i.e. it must
59    /// be paired with a successful call to [`lock`], [`try_lock`], [`try_lock_for`] or [`try_lock_until`].
60    ///
61    /// [`lock`]: RawMutex::lock
62    /// [`try_lock`]: RawMutex::try_lock
63    /// [`try_lock_for`]: RawMutexTimed::try_lock_for
64    /// [`try_lock_until`]: RawMutexTimed::try_lock_until
65    unsafe fn unlock(&self);
66
67    /// Checks whether the mutex is currently locked.
68    #[inline]
69    fn is_locked(&self) -> bool {
70        let acquired_lock = self.try_lock();
71        if acquired_lock {
72            // Safety: The lock has been successfully acquired above.
73            unsafe {
74                self.unlock();
75            }
76        }
77        !acquired_lock
78    }
79}
80
81/// Additional methods for mutexes which support fair unlocking.
82///
83/// Fair unlocking means that a lock is handed directly over to the next waiting
84/// thread if there is one, without giving other threads the opportunity to
85/// "steal" the lock in the meantime. This is typically slower than unfair
86/// unlocking, but may be necessary in certain circumstances.
87pub unsafe trait RawMutexFair: RawMutex {
88    /// Unlocks this mutex using a fair unlock protocol.
89    ///
90    /// # Safety
91    ///
92    /// This method may only be called if the mutex is held in the current context, see
93    /// the documentation of [`unlock`](RawMutex::unlock).
94    unsafe fn unlock_fair(&self);
95
96    /// Temporarily yields the mutex to a waiting thread if there is one.
97    ///
98    /// This method is functionally equivalent to calling `unlock_fair` followed
99    /// by `lock`, however it can be much more efficient in the case where there
100    /// are no waiting threads.
101    ///
102    /// # Safety
103    ///
104    /// This method may only be called if the mutex is held in the current context, see
105    /// the documentation of [`unlock`](RawMutex::unlock).
106    unsafe fn bump(&self) {
107        self.unlock_fair();
108        self.lock();
109    }
110}
111
112/// Additional methods for mutexes which support locking with timeouts.
113///
114/// The `Duration` and `Instant` types are specified as associated types so that
115/// this trait is usable even in `no_std` environments.
116pub unsafe trait RawMutexTimed: RawMutex {
117    /// Duration type used for `try_lock_for`.
118    type Duration;
119
120    /// Instant type used for `try_lock_until`.
121    type Instant;
122
123    /// Attempts to acquire this lock until a timeout is reached.
124    fn try_lock_for(&self, timeout: Self::Duration) -> bool;
125
126    /// Attempts to acquire this lock until a timeout is reached.
127    fn try_lock_until(&self, timeout: Self::Instant) -> bool;
128}
129
130/// A mutual exclusion primitive useful for protecting shared data
131///
132/// This mutex will block threads waiting for the lock to become available. The
133/// mutex can also be statically initialized or created via a `new`
134/// constructor. Each mutex has a type parameter which represents the data that
135/// it is protecting. The data can only be accessed through the RAII guards
136/// returned from `lock` and `try_lock`, which guarantees that the data is only
137/// ever accessed when the mutex is locked.
138pub struct Mutex<R, T: ?Sized> {
139    raw: R,
140    data: UnsafeCell<T>,
141}
142
143unsafe impl<R: RawMutex + Send, T: ?Sized + Send> Send for Mutex<R, T> {}
144unsafe impl<R: RawMutex + Sync, T: ?Sized + Send> Sync for Mutex<R, T> {}
145
146impl<R: RawMutex, T> Mutex<R, T> {
147    /// Creates a new mutex in an unlocked state ready for use.
148    #[inline]
149    pub const fn new(val: T) -> Mutex<R, T> {
150        Mutex {
151            raw: R::INIT,
152            data: UnsafeCell::new(val),
153        }
154    }
155
156    /// Consumes this mutex, returning the underlying data.
157    #[inline]
158    pub fn into_inner(self) -> T {
159        self.data.into_inner()
160    }
161}
162
163impl<R, T> Mutex<R, T> {
164    /// Creates a new mutex based on a pre-existing raw mutex.
165    #[inline]
166    pub const fn from_raw(raw_mutex: R, val: T) -> Mutex<R, T> {
167        Mutex {
168            raw: raw_mutex,
169            data: UnsafeCell::new(val),
170        }
171    }
172
173    /// Creates a new mutex based on a pre-existing raw mutex.
174    ///
175    /// This allows creating a mutex in a constant context on stable Rust.
176    ///
177    /// This method is a legacy alias for [`from_raw`](Self::from_raw).
178    #[inline]
179    pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> {
180        Self::from_raw(raw_mutex, val)
181    }
182
183    /// Consumes this mutex, returning the underlying data and raw mutex.
184    #[inline]
185    pub fn into_inner_with_raw(self) -> (R, T) {
186        (self.raw, self.data.into_inner())
187    }
188}
189
190impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
191    /// Creates a new `MutexGuard` without checking if the mutex is locked.
192    ///
193    /// # Safety
194    ///
195    /// This method must only be called if the thread logically holds the lock.
196    ///
197    /// Calling this function when a guard has already been produced is undefined behaviour unless
198    /// the guard was forgotten with `mem::forget`.
199    #[inline]
200    pub unsafe fn make_guard_unchecked(&self) -> MutexGuard<'_, R, T> {
201        MutexGuard {
202            mutex: self,
203            marker: PhantomData,
204        }
205    }
206
207    /// Acquires a mutex, blocking the current thread until it is able to do so.
208    ///
209    /// This function will block the local thread until it is available to acquire
210    /// the mutex. Upon returning, the thread is the only thread with the mutex
211    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
212    /// the guard goes out of scope, the mutex will be unlocked.
213    ///
214    /// Attempts to lock a mutex in the thread which already holds the lock will
215    /// result in a deadlock.
216    #[inline]
217    #[track_caller]
218    pub fn lock(&self) -> MutexGuard<'_, R, T> {
219        self.raw.lock();
220        // SAFETY: The lock is held, as required.
221        unsafe { self.make_guard_unchecked() }
222    }
223
224    /// Attempts to acquire this lock.
225    ///
226    /// If the lock could not be acquired at this time, then `None` is returned.
227    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
228    /// guard is dropped.
229    ///
230    /// This function does not block.
231    #[inline]
232    #[track_caller]
233    pub fn try_lock(&self) -> Option<MutexGuard<'_, R, T>> {
234        if self.raw.try_lock() {
235            // SAFETY: The lock is held, as required.
236            Some(unsafe { self.make_guard_unchecked() })
237        } else {
238            None
239        }
240    }
241
242    /// Returns a mutable reference to the underlying data.
243    ///
244    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
245    /// take place---the mutable borrow statically guarantees no locks exist.
246    #[inline]
247    pub fn get_mut(&mut self) -> &mut T {
248        unsafe { &mut *self.data.get() }
249    }
250
251    /// Checks whether the mutex is currently locked.
252    #[inline]
253    #[track_caller]
254    pub fn is_locked(&self) -> bool {
255        self.raw.is_locked()
256    }
257
258    /// Forcibly unlocks the mutex.
259    ///
260    /// This is useful when combined with `mem::forget` to hold a lock without
261    /// the need to maintain a `MutexGuard` object alive, for example when
262    /// dealing with FFI.
263    ///
264    /// # Safety
265    ///
266    /// This method must only be called if the current thread logically owns a
267    /// `MutexGuard` but that guard has been discarded using `mem::forget`.
268    /// Behavior is undefined if a mutex is unlocked when not locked.
269    #[inline]
270    #[track_caller]
271    pub unsafe fn force_unlock(&self) {
272        self.raw.unlock();
273    }
274
275    /// Returns the underlying raw mutex object.
276    ///
277    /// Note that you will most likely need to import the `RawMutex` trait from
278    /// `lock_api` to be able to call functions on the raw mutex.
279    ///
280    /// # Safety
281    ///
282    /// This method is unsafe because it allows unlocking a mutex while
283    /// still holding a reference to a `MutexGuard`.
284    #[inline]
285    pub unsafe fn raw(&self) -> &R {
286        &self.raw
287    }
288
289    /// Returns a raw pointer to the underlying data.
290    ///
291    /// This is useful when combined with `mem::forget` to hold a lock without
292    /// the need to maintain a `MutexGuard` object alive, for example when
293    /// dealing with FFI.
294    ///
295    /// # Safety
296    ///
297    /// You must ensure that there are no data races when dereferencing the
298    /// returned pointer, for example if the current thread logically owns
299    /// a `MutexGuard` but that guard has been discarded using `mem::forget`.
300    #[inline]
301    pub fn data_ptr(&self) -> *mut T {
302        self.data.get()
303    }
304
305    /// Creates a new `ArcMutexGuard` without checking if the mutex is locked.
306    ///
307    /// # Safety
308    ///
309    /// This method must only be called if the thread logically holds the lock.
310    ///
311    /// Calling this function when a guard has already been produced is undefined behaviour unless
312    /// the guard was forgotten with `mem::forget`.
313    #[cfg(feature = "arc_lock")]
314    #[inline]
315    unsafe fn make_arc_guard_unchecked(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
316        ArcMutexGuard {
317            mutex: self.clone(),
318            marker: PhantomData,
319        }
320    }
321
322    /// Acquires a lock through an `Arc`.
323    ///
324    /// This method is similar to the `lock` method; however, it requires the `Mutex` to be inside of an `Arc`
325    /// and the resulting mutex guard has no lifetime requirements.
326    #[cfg(feature = "arc_lock")]
327    #[inline]
328    #[track_caller]
329    pub fn lock_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
330        self.raw.lock();
331        // SAFETY: the locking guarantee is upheld
332        unsafe { self.make_arc_guard_unchecked() }
333    }
334
335    /// Attempts to acquire a lock through an `Arc`.
336    ///
337    /// This method is similar to the `try_lock` method; however, it requires the `Mutex` to be inside of an
338    /// `Arc` and the resulting mutex guard has no lifetime requirements.
339    #[cfg(feature = "arc_lock")]
340    #[inline]
341    #[track_caller]
342    pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<R, T>> {
343        if self.raw.try_lock() {
344            // SAFETY: locking guarantee is upheld
345            Some(unsafe { self.make_arc_guard_unchecked() })
346        } else {
347            None
348        }
349    }
350}
351
352impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> {
353    /// Forcibly unlocks the mutex using a fair unlock protocol.
354    ///
355    /// This is useful when combined with `mem::forget` to hold a lock without
356    /// the need to maintain a `MutexGuard` object alive, for example when
357    /// dealing with FFI.
358    ///
359    /// # Safety
360    ///
361    /// This method must only be called if the current thread logically owns a
362    /// `MutexGuard` but that guard has been discarded using `mem::forget`.
363    /// Behavior is undefined if a mutex is unlocked when not locked.
364    #[inline]
365    #[track_caller]
366    pub unsafe fn force_unlock_fair(&self) {
367        self.raw.unlock_fair();
368    }
369}
370
371impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
372    /// Attempts to acquire this lock until a timeout is reached.
373    ///
374    /// If the lock could not be acquired before the timeout expired, then
375    /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
376    /// be unlocked when the guard is dropped.
377    #[inline]
378    #[track_caller]
379    pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>> {
380        if self.raw.try_lock_for(timeout) {
381            // SAFETY: The lock is held, as required.
382            Some(unsafe { self.make_guard_unchecked() })
383        } else {
384            None
385        }
386    }
387
388    /// Attempts to acquire this lock until a timeout is reached.
389    ///
390    /// If the lock could not be acquired before the timeout expired, then
391    /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
392    /// be unlocked when the guard is dropped.
393    #[inline]
394    #[track_caller]
395    pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>> {
396        if self.raw.try_lock_until(timeout) {
397            // SAFETY: The lock is held, as required.
398            Some(unsafe { self.make_guard_unchecked() })
399        } else {
400            None
401        }
402    }
403
404    /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
405    ///
406    /// This method is similar to the `try_lock_for` method; however, it requires the `Mutex` to be inside of an
407    /// `Arc` and the resulting mutex guard has no lifetime requirements.
408    #[cfg(feature = "arc_lock")]
409    #[inline]
410    #[track_caller]
411    pub fn try_lock_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcMutexGuard<R, T>> {
412        if self.raw.try_lock_for(timeout) {
413            // SAFETY: locking guarantee is upheld
414            Some(unsafe { self.make_arc_guard_unchecked() })
415        } else {
416            None
417        }
418    }
419
420    /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
421    ///
422    /// This method is similar to the `try_lock_until` method; however, it requires the `Mutex` to be inside of
423    /// an `Arc` and the resulting mutex guard has no lifetime requirements.
424    #[cfg(feature = "arc_lock")]
425    #[inline]
426    #[track_caller]
427    pub fn try_lock_arc_until(
428        self: &Arc<Self>,
429        timeout: R::Instant,
430    ) -> Option<ArcMutexGuard<R, T>> {
431        if self.raw.try_lock_until(timeout) {
432            // SAFETY: locking guarantee is upheld
433            Some(unsafe { self.make_arc_guard_unchecked() })
434        } else {
435            None
436        }
437    }
438}
439
440impl<R: RawMutex, T: ?Sized + Default> Default for Mutex<R, T> {
441    #[inline]
442    fn default() -> Mutex<R, T> {
443        Mutex::new(Default::default())
444    }
445}
446
447impl<R: RawMutex, T> From<T> for Mutex<R, T> {
448    #[inline]
449    fn from(t: T) -> Mutex<R, T> {
450        Mutex::new(t)
451    }
452}
453
454impl<R: RawMutex, T: ?Sized + fmt::Debug> fmt::Debug for Mutex<R, T> {
455    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456        match self.try_lock() {
457            Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
458            None => {
459                struct LockedPlaceholder;
460                impl fmt::Debug for LockedPlaceholder {
461                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
462                        f.write_str("<locked>")
463                    }
464                }
465
466                f.debug_struct("Mutex")
467                    .field("data", &LockedPlaceholder)
468                    .finish()
469            }
470        }
471    }
472}
473
474// Copied and modified from serde
475#[cfg(feature = "serde")]
476impl<R, T> Serialize for Mutex<R, T>
477where
478    R: RawMutex,
479    T: Serialize + ?Sized,
480{
481    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
482    where
483        S: Serializer,
484    {
485        self.lock().serialize(serializer)
486    }
487}
488
489#[cfg(feature = "serde")]
490impl<'de, R, T> Deserialize<'de> for Mutex<R, T>
491where
492    R: RawMutex,
493    T: Deserialize<'de> + ?Sized,
494{
495    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
496    where
497        D: Deserializer<'de>,
498    {
499        Deserialize::deserialize(deserializer).map(Mutex::new)
500    }
501}
502
503/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
504/// dropped (falls out of scope), the lock will be unlocked.
505///
506/// The data protected by the mutex can be accessed through this guard via its
507/// `Deref` and `DerefMut` implementations.
508#[clippy::has_significant_drop]
509#[must_use = "if unused the Mutex will immediately unlock"]
510pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> {
511    mutex: &'a Mutex<R, T>,
512    marker: PhantomData<(&'a mut T, R::GuardMarker)>,
513}
514
515unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {}
516
517impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
518    /// Returns a reference to the original `Mutex` object.
519    pub fn mutex(s: &Self) -> &'a Mutex<R, T> {
520        s.mutex
521    }
522
523    /// Makes a new `MappedMutexGuard` for a component of the locked data.
524    ///
525    /// This operation cannot fail as the `MutexGuard` passed
526    /// in already locked the mutex.
527    ///
528    /// This is an associated function that needs to be
529    /// used as `MutexGuard::map(...)`. A method would interfere with methods of
530    /// the same name on the contents of the locked data.
531    #[inline]
532    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
533    where
534        F: FnOnce(&mut T) -> &mut U,
535    {
536        let raw = &s.mutex.raw;
537        let data = f(unsafe { &mut *s.mutex.data.get() });
538        mem::forget(s);
539        MappedMutexGuard {
540            raw,
541            data,
542            marker: PhantomData,
543        }
544    }
545
546    /// Attempts to make a new `MappedMutexGuard` for a component of the
547    /// locked data. The original guard is returned if the closure returns `None`.
548    ///
549    /// This operation cannot fail as the `MutexGuard` passed
550    /// in already locked the mutex.
551    ///
552    /// This is an associated function that needs to be
553    /// used as `MutexGuard::try_map(...)`. A method would interfere with methods of
554    /// the same name on the contents of the locked data.
555    #[inline]
556    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
557    where
558        F: FnOnce(&mut T) -> Option<&mut U>,
559    {
560        let raw = &s.mutex.raw;
561        let data = match f(unsafe { &mut *s.mutex.data.get() }) {
562            Some(data) => data,
563            None => return Err(s),
564        };
565        mem::forget(s);
566        Ok(MappedMutexGuard {
567            raw,
568            data,
569            marker: PhantomData,
570        })
571    }
572
573    /// Attempts to make a new `MappedMutexGuard` for a component of the
574    /// locked data. The original guard is returned alongside arbitrary user data
575    /// if the closure returns `Err`.
576    ///
577    /// This operation cannot fail as the `MutexGuard` passed
578    /// in already locked the mutex.
579    ///
580    /// This is an associated function that needs to be
581    /// used as `MutexGuard::try_map_or_err(...)`. A method would interfere with methods of
582    /// the same name on the contents of the locked data.
583    #[inline]
584    pub fn try_map_or_err<U: ?Sized, F, E>(
585        s: Self,
586        f: F,
587    ) -> Result<MappedMutexGuard<'a, R, U>, (Self, E)>
588    where
589        F: FnOnce(&mut T) -> Result<&mut U, E>,
590    {
591        let raw = &s.mutex.raw;
592        let data = match f(unsafe { &mut *s.mutex.data.get() }) {
593            Ok(data) => data,
594            Err(e) => return Err((s, e)),
595        };
596        mem::forget(s);
597        Ok(MappedMutexGuard {
598            raw,
599            data,
600            marker: PhantomData,
601        })
602    }
603
604    /// Temporarily unlocks the mutex to execute the given function.
605    ///
606    /// This is safe because `&mut` guarantees that there exist no other
607    /// references to the data protected by the mutex.
608    #[inline]
609    #[track_caller]
610    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
611    where
612        F: FnOnce() -> U,
613    {
614        // Safety: A MutexGuard always holds the lock.
615        unsafe {
616            s.mutex.raw.unlock();
617        }
618        defer!(s.mutex.raw.lock());
619        f()
620    }
621
622    /// Leaks the mutex guard and returns a mutable reference to the data
623    /// protected by the mutex.
624    ///
625    /// This will leave the `Mutex` in a locked state.
626    #[inline]
627    pub fn leak(s: Self) -> &'a mut T {
628        let r = unsafe { &mut *s.mutex.data.get() };
629        mem::forget(s);
630        r
631    }
632}
633
634impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
635    /// Unlocks the mutex using a fair unlock protocol.
636    ///
637    /// By default, mutexes are unfair and allow the current thread to re-lock
638    /// the mutex before another has the chance to acquire the lock, even if
639    /// that thread has been blocked on the mutex for a long time. This is the
640    /// default because it allows much higher throughput as it avoids forcing a
641    /// context switch on every mutex unlock. This can result in one thread
642    /// acquiring a mutex many more times than other threads.
643    ///
644    /// However in some cases it can be beneficial to ensure fairness by forcing
645    /// the lock to pass on to a waiting thread if there is one. This is done by
646    /// using this method instead of dropping the `MutexGuard` normally.
647    #[inline]
648    #[track_caller]
649    pub fn unlock_fair(s: Self) {
650        // Safety: A MutexGuard always holds the lock.
651        unsafe {
652            s.mutex.raw.unlock_fair();
653        }
654        mem::forget(s);
655    }
656
657    /// Temporarily unlocks the mutex to execute the given function.
658    ///
659    /// The mutex is unlocked using a fair unlock protocol.
660    ///
661    /// This is safe because `&mut` guarantees that there exist no other
662    /// references to the data protected by the mutex.
663    #[inline]
664    #[track_caller]
665    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
666    where
667        F: FnOnce() -> U,
668    {
669        // Safety: A MutexGuard always holds the lock.
670        unsafe {
671            s.mutex.raw.unlock_fair();
672        }
673        defer!(s.mutex.raw.lock());
674        f()
675    }
676
677    /// Temporarily yields the mutex to a waiting thread if there is one.
678    ///
679    /// This method is functionally equivalent to calling `unlock_fair` followed
680    /// by `lock`, however it can be much more efficient in the case where there
681    /// are no waiting threads.
682    #[inline]
683    #[track_caller]
684    pub fn bump(s: &mut Self) {
685        // Safety: A MutexGuard always holds the lock.
686        unsafe {
687            s.mutex.raw.bump();
688        }
689    }
690}
691
692impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> {
693    type Target = T;
694    #[inline]
695    fn deref(&self) -> &T {
696        unsafe { &*self.mutex.data.get() }
697    }
698}
699
700impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> {
701    #[inline]
702    fn deref_mut(&mut self) -> &mut T {
703        unsafe { &mut *self.mutex.data.get() }
704    }
705}
706
707impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> {
708    #[inline]
709    fn drop(&mut self) {
710        // Safety: A MutexGuard always holds the lock.
711        unsafe {
712            self.mutex.raw.unlock();
713        }
714    }
715}
716
717impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> {
718    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
719        fmt::Debug::fmt(&**self, f)
720    }
721}
722
723impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> {
724    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
725        (**self).fmt(f)
726    }
727}
728
729#[cfg(feature = "owning_ref")]
730unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {}
731
732/// An RAII mutex guard returned by the `Arc` locking operations on `Mutex`.
733///
734/// This is similar to the `MutexGuard` struct, except instead of using a reference to unlock the `Mutex` it
735/// uses an `Arc<Mutex>`. This has several advantages, most notably that it has an `'static` lifetime.
736#[cfg(feature = "arc_lock")]
737#[clippy::has_significant_drop]
738#[must_use = "if unused the Mutex will immediately unlock"]
739pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> {
740    mutex: Arc<Mutex<R, T>>,
741    marker: PhantomData<*const ()>,
742}
743
744#[cfg(feature = "arc_lock")]
745unsafe impl<R: RawMutex + Send + Sync, T: Send + ?Sized> Send for ArcMutexGuard<R, T> where
746    R::GuardMarker: Send
747{
748}
749#[cfg(feature = "arc_lock")]
750unsafe impl<R: RawMutex + Sync, T: Sync + ?Sized> Sync for ArcMutexGuard<R, T> where
751    R::GuardMarker: Sync
752{
753}
754
755#[cfg(feature = "arc_lock")]
756impl<R: RawMutex, T: ?Sized> ArcMutexGuard<R, T> {
757    /// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`.
758    #[inline]
759    pub fn mutex(s: &Self) -> &Arc<Mutex<R, T>> {
760        &s.mutex
761    }
762
763    /// Unlocks the mutex and returns the `Arc` that was held by the [`ArcMutexGuard`].
764    #[inline]
765    #[track_caller]
766    pub fn into_arc(s: Self) -> Arc<Mutex<R, T>> {
767        // SAFETY: Skip our Drop impl and manually unlock the mutex.
768        let s = ManuallyDrop::new(s);
769        unsafe {
770            s.mutex.raw.unlock();
771            ptr::read(&s.mutex)
772        }
773    }
774
775    /// Temporarily unlocks the mutex to execute the given function.
776    ///
777    /// This is safe because `&mut` guarantees that there exist no other
778    /// references to the data protected by the mutex.
779    #[inline]
780    #[track_caller]
781    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
782    where
783        F: FnOnce() -> U,
784    {
785        // Safety: A MutexGuard always holds the lock.
786        unsafe {
787            s.mutex.raw.unlock();
788        }
789        defer!(s.mutex.raw.lock());
790        f()
791    }
792}
793
794#[cfg(feature = "arc_lock")]
795impl<R: RawMutexFair, T: ?Sized> ArcMutexGuard<R, T> {
796    /// Unlocks the mutex using a fair unlock protocol.
797    ///
798    /// This is functionally identical to the `unlock_fair` method on [`MutexGuard`].
799    #[inline]
800    #[track_caller]
801    pub fn unlock_fair(s: Self) {
802        drop(Self::into_arc_fair(s));
803    }
804
805    /// Unlocks the mutex using a fair unlock protocol and returns the `Arc` that was held by the [`ArcMutexGuard`].
806    #[inline]
807    pub fn into_arc_fair(s: Self) -> Arc<Mutex<R, T>> {
808        // SAFETY: Skip our Drop impl and manually unlock the mutex.
809        let s = ManuallyDrop::new(s);
810        unsafe {
811            s.mutex.raw.unlock_fair();
812            ptr::read(&s.mutex)
813        }
814    }
815
816    /// Temporarily unlocks the mutex to execute the given function.
817    ///
818    /// This is functionally identical to the `unlocked_fair` method on [`MutexGuard`].
819    #[inline]
820    #[track_caller]
821    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
822    where
823        F: FnOnce() -> U,
824    {
825        // Safety: A MutexGuard always holds the lock.
826        unsafe {
827            s.mutex.raw.unlock_fair();
828        }
829        defer!(s.mutex.raw.lock());
830        f()
831    }
832
833    /// Temporarily yields the mutex to a waiting thread if there is one.
834    ///
835    /// This is functionally identical to the `bump` method on [`MutexGuard`].
836    #[inline]
837    #[track_caller]
838    pub fn bump(s: &mut Self) {
839        // Safety: A MutexGuard always holds the lock.
840        unsafe {
841            s.mutex.raw.bump();
842        }
843    }
844}
845
846#[cfg(feature = "arc_lock")]
847impl<R: RawMutex, T: ?Sized> Deref for ArcMutexGuard<R, T> {
848    type Target = T;
849    #[inline]
850    fn deref(&self) -> &T {
851        unsafe { &*self.mutex.data.get() }
852    }
853}
854
855#[cfg(feature = "arc_lock")]
856impl<R: RawMutex, T: ?Sized> DerefMut for ArcMutexGuard<R, T> {
857    #[inline]
858    fn deref_mut(&mut self) -> &mut T {
859        unsafe { &mut *self.mutex.data.get() }
860    }
861}
862
863#[cfg(feature = "arc_lock")]
864impl<R: RawMutex, T: ?Sized> Drop for ArcMutexGuard<R, T> {
865    #[inline]
866    fn drop(&mut self) {
867        // Safety: A MutexGuard always holds the lock.
868        unsafe {
869            self.mutex.raw.unlock();
870        }
871    }
872}
873
874/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a
875/// subfield of the protected data.
876///
877/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the
878/// former doesn't support temporarily unlocking and re-locking, since that
879/// could introduce soundness issues if the locked object is modified by another
880/// thread.
881#[clippy::has_significant_drop]
882#[must_use = "if unused the Mutex will immediately unlock"]
883pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> {
884    raw: &'a R,
885    data: *mut T,
886    marker: PhantomData<&'a mut T>,
887}
888
889unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync
890    for MappedMutexGuard<'a, R, T>
891{
892}
893unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + Send + 'a> Send for MappedMutexGuard<'a, R, T> where
894    R::GuardMarker: Send
895{
896}
897
898impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
899    /// Makes a new `MappedMutexGuard` for a component of the locked data.
900    ///
901    /// This operation cannot fail as the `MappedMutexGuard` passed
902    /// in already locked the mutex.
903    ///
904    /// This is an associated function that needs to be
905    /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of
906    /// the same name on the contents of the locked data.
907    #[inline]
908    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
909    where
910        F: FnOnce(&mut T) -> &mut U,
911    {
912        let raw = s.raw;
913        let data = f(unsafe { &mut *s.data });
914        mem::forget(s);
915        MappedMutexGuard {
916            raw,
917            data,
918            marker: PhantomData,
919        }
920    }
921
922    /// Attempts to make a new `MappedMutexGuard` for a component of the
923    /// locked data. The original guard is returned if the closure returns `None`.
924    ///
925    /// This operation cannot fail as the `MappedMutexGuard` passed
926    /// in already locked the mutex.
927    ///
928    /// This is an associated function that needs to be
929    /// used as `MappedMutexGuard::try_map(...)`. A method would interfere with methods of
930    /// the same name on the contents of the locked data.
931    #[inline]
932    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
933    where
934        F: FnOnce(&mut T) -> Option<&mut U>,
935    {
936        let raw = s.raw;
937        let data = match f(unsafe { &mut *s.data }) {
938            Some(data) => data,
939            None => return Err(s),
940        };
941        mem::forget(s);
942        Ok(MappedMutexGuard {
943            raw,
944            data,
945            marker: PhantomData,
946        })
947    }
948
949    /// Attempts to make a new `MappedMutexGuard` for a component of the
950    /// locked data. The original guard is returned alongside arbitrary user data
951    /// if the closure returns `Err`.
952    ///
953    /// This operation cannot fail as the `MappedMutexGuard` passed
954    /// in already locked the mutex.
955    ///
956    /// This is an associated function that needs to be
957    /// used as `MappedMutexGuard::try_map_or_err(...)`. A method would interfere with methods of
958    /// the same name on the contents of the locked data.
959    #[inline]
960    pub fn try_map_or_err<U: ?Sized, F, E>(
961        s: Self,
962        f: F,
963    ) -> Result<MappedMutexGuard<'a, R, U>, (Self, E)>
964    where
965        F: FnOnce(&mut T) -> Result<&mut U, E>,
966    {
967        let raw = s.raw;
968        let data = match f(unsafe { &mut *s.data }) {
969            Ok(data) => data,
970            Err(e) => return Err((s, e)),
971        };
972        mem::forget(s);
973        Ok(MappedMutexGuard {
974            raw,
975            data,
976            marker: PhantomData,
977        })
978    }
979}
980
981impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
982    /// Unlocks the mutex using a fair unlock protocol.
983    ///
984    /// By default, mutexes are unfair and allow the current thread to re-lock
985    /// the mutex before another has the chance to acquire the lock, even if
986    /// that thread has been blocked on the mutex for a long time. This is the
987    /// default because it allows much higher throughput as it avoids forcing a
988    /// context switch on every mutex unlock. This can result in one thread
989    /// acquiring a mutex many more times than other threads.
990    ///
991    /// However in some cases it can be beneficial to ensure fairness by forcing
992    /// the lock to pass on to a waiting thread if there is one. This is done by
993    /// using this method instead of dropping the `MutexGuard` normally.
994    #[inline]
995    #[track_caller]
996    pub fn unlock_fair(s: Self) {
997        // Safety: A MutexGuard always holds the lock.
998        unsafe {
999            s.raw.unlock_fair();
1000        }
1001        mem::forget(s);
1002    }
1003}
1004
1005impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> {
1006    type Target = T;
1007    #[inline]
1008    fn deref(&self) -> &T {
1009        unsafe { &*self.data }
1010    }
1011}
1012
1013impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> {
1014    #[inline]
1015    fn deref_mut(&mut self) -> &mut T {
1016        unsafe { &mut *self.data }
1017    }
1018}
1019
1020impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> {
1021    #[inline]
1022    fn drop(&mut self) {
1023        // Safety: A MappedMutexGuard always holds the lock.
1024        unsafe {
1025            self.raw.unlock();
1026        }
1027    }
1028}
1029
1030impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> {
1031    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1032        fmt::Debug::fmt(&**self, f)
1033    }
1034}
1035
1036impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
1037    for MappedMutexGuard<'a, R, T>
1038{
1039    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1040        (**self).fmt(f)
1041    }
1042}
1043
1044#[cfg(feature = "owning_ref")]
1045unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {}