Skip to main content

lock_api/
mutex.rs

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