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    #[cfg(has_const_fn_trait_bound)]
149    #[inline]
150    pub const fn new(val: T) -> Mutex<R, T> {
151        Mutex {
152            raw: R::INIT,
153            data: UnsafeCell::new(val),
154        }
155    }
156
157    /// Creates a new mutex in an unlocked state ready for use.
158    #[cfg(not(has_const_fn_trait_bound))]
159    #[inline]
160    pub fn new(val: T) -> Mutex<R, T> {
161        Mutex {
162            raw: R::INIT,
163            data: UnsafeCell::new(val),
164        }
165    }
166
167    /// Consumes this mutex, returning the underlying data.
168    #[inline]
169    pub fn into_inner(self) -> T {
170        self.data.into_inner()
171    }
172}
173
174impl<R, T> Mutex<R, T> {
175    /// Creates a new mutex based on a pre-existing raw mutex.
176    #[inline]
177    pub const fn from_raw(raw_mutex: R, val: T) -> Mutex<R, T> {
178        Mutex {
179            raw: raw_mutex,
180            data: UnsafeCell::new(val),
181        }
182    }
183
184    /// Creates a new mutex based on a pre-existing raw mutex.
185    ///
186    /// This allows creating a mutex in a constant context on stable Rust.
187    ///
188    /// This method is a legacy alias for [`from_raw`](Self::from_raw).
189    #[inline]
190    pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> {
191        Self::from_raw(raw_mutex, val)
192    }
193}
194
195impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
196    /// Creates a new `MutexGuard` without checking if the mutex is locked.
197    ///
198    /// # Safety
199    ///
200    /// This method must only be called if the thread logically holds the lock.
201    ///
202    /// Calling this function when a guard has already been produced is undefined behaviour unless
203    /// the guard was forgotten with `mem::forget`.
204    #[inline]
205    pub unsafe fn make_guard_unchecked(&self) -> MutexGuard<'_, R, T> {
206        MutexGuard {
207            mutex: self,
208            marker: PhantomData,
209        }
210    }
211
212    /// Acquires a mutex, blocking the current thread until it is able to do so.
213    ///
214    /// This function will block the local thread until it is available to acquire
215    /// the mutex. Upon returning, the thread is the only thread with the mutex
216    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
217    /// the guard goes out of scope, the mutex will be unlocked.
218    ///
219    /// Attempts to lock a mutex in the thread which already holds the lock will
220    /// result in a deadlock.
221    #[inline]
222    pub fn lock(&self) -> MutexGuard<'_, R, T> {
223        self.raw.lock();
224        // SAFETY: The lock is held, as required.
225        unsafe { self.make_guard_unchecked() }
226    }
227
228    /// Attempts to acquire this lock.
229    ///
230    /// If the lock could not be acquired at this time, then `None` is returned.
231    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
232    /// guard is dropped.
233    ///
234    /// This function does not block.
235    #[inline]
236    pub fn try_lock(&self) -> Option<MutexGuard<'_, R, T>> {
237        if self.raw.try_lock() {
238            // SAFETY: The lock is held, as required.
239            Some(unsafe { self.make_guard_unchecked() })
240        } else {
241            None
242        }
243    }
244
245    /// Returns a mutable reference to the underlying data.
246    ///
247    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
248    /// take place---the mutable borrow statically guarantees no locks exist.
249    #[inline]
250    pub fn get_mut(&mut self) -> &mut T {
251        unsafe { &mut *self.data.get() }
252    }
253
254    /// Checks whether the mutex is currently locked.
255    #[inline]
256    pub fn is_locked(&self) -> bool {
257        self.raw.is_locked()
258    }
259
260    /// Forcibly unlocks the mutex.
261    ///
262    /// This is useful when combined with `mem::forget` to hold a lock without
263    /// the need to maintain a `MutexGuard` object alive, for example when
264    /// dealing with FFI.
265    ///
266    /// # Safety
267    ///
268    /// This method must only be called if the current thread logically owns a
269    /// `MutexGuard` but that guard has been discarded using `mem::forget`.
270    /// Behavior is undefined if a mutex is unlocked when not locked.
271    #[inline]
272    pub unsafe fn force_unlock(&self) {
273        self.raw.unlock();
274    }
275
276    /// Returns the underlying raw mutex object.
277    ///
278    /// Note that you will most likely need to import the `RawMutex` trait from
279    /// `lock_api` to be able to call functions on the raw mutex.
280    ///
281    /// # Safety
282    ///
283    /// This method is unsafe because it allows unlocking a mutex while
284    /// still holding a reference to a `MutexGuard`.
285    #[inline]
286    pub unsafe fn raw(&self) -> &R {
287        &self.raw
288    }
289
290    /// Returns a raw pointer to the underlying data.
291    ///
292    /// This is useful when combined with `mem::forget` to hold a lock without
293    /// the need to maintain a `MutexGuard` object alive, for example when
294    /// dealing with FFI.
295    ///
296    /// # Safety
297    ///
298    /// You must ensure that there are no data races when dereferencing the
299    /// returned pointer, for example if the current thread logically owns
300    /// a `MutexGuard` but that guard has been discarded using `mem::forget`.
301    #[inline]
302    pub fn data_ptr(&self) -> *mut T {
303        self.data.get()
304    }
305
306    /// Creates a new `ArcMutexGuard` without checking if the mutex is locked.
307    ///
308    /// # Safety
309    ///
310    /// This method must only be called if the thread logically holds the lock.
311    ///
312    /// Calling this function when a guard has already been produced is undefined behaviour unless
313    /// the guard was forgotten with `mem::forget`.
314    #[cfg(feature = "arc_lock")]
315    #[inline]
316    unsafe fn make_arc_guard_unchecked(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
317        ArcMutexGuard {
318            mutex: self.clone(),
319            marker: PhantomData,
320        }
321    }
322
323    /// Acquires a lock through an `Arc`.
324    ///
325    /// This method is similar to the `lock` method; however, it requires the `Mutex` to be inside of an `Arc`
326    /// and the resulting mutex guard has no lifetime requirements.
327    #[cfg(feature = "arc_lock")]
328    #[inline]
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    pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<R, T>> {
342        if self.raw.try_lock() {
343            // SAFETY: locking guarantee is upheld
344            Some(unsafe { self.make_arc_guard_unchecked() })
345        } else {
346            None
347        }
348    }
349}
350
351impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> {
352    /// Forcibly unlocks the mutex using a fair unlock protocol.
353    ///
354    /// This is useful when combined with `mem::forget` to hold a lock without
355    /// the need to maintain a `MutexGuard` object alive, for example when
356    /// dealing with FFI.
357    ///
358    /// # Safety
359    ///
360    /// This method must only be called if the current thread logically owns a
361    /// `MutexGuard` but that guard has been discarded using `mem::forget`.
362    /// Behavior is undefined if a mutex is unlocked when not locked.
363    #[inline]
364    pub unsafe fn force_unlock_fair(&self) {
365        self.raw.unlock_fair();
366    }
367}
368
369impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
370    /// Attempts to acquire this lock until a timeout is reached.
371    ///
372    /// If the lock could not be acquired before the timeout expired, then
373    /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
374    /// be unlocked when the guard is dropped.
375    #[inline]
376    pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>> {
377        if self.raw.try_lock_for(timeout) {
378            // SAFETY: The lock is held, as required.
379            Some(unsafe { self.make_guard_unchecked() })
380        } else {
381            None
382        }
383    }
384
385    /// Attempts to acquire this lock until a timeout is reached.
386    ///
387    /// If the lock could not be acquired before the timeout expired, then
388    /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
389    /// be unlocked when the guard is dropped.
390    #[inline]
391    pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>> {
392        if self.raw.try_lock_until(timeout) {
393            // SAFETY: The lock is held, as required.
394            Some(unsafe { self.make_guard_unchecked() })
395        } else {
396            None
397        }
398    }
399
400    /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
401    ///
402    /// This method is similar to the `try_lock_for` method; however, it requires the `Mutex` to be inside of an
403    /// `Arc` and the resulting mutex guard has no lifetime requirements.
404    #[cfg(feature = "arc_lock")]
405    #[inline]
406    pub fn try_lock_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcMutexGuard<R, T>> {
407        if self.raw.try_lock_for(timeout) {
408            // SAFETY: locking guarantee is upheld
409            Some(unsafe { self.make_arc_guard_unchecked() })
410        } else {
411            None
412        }
413    }
414
415    /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
416    ///
417    /// This method is similar to the `try_lock_until` method; however, it requires the `Mutex` to be inside of
418    /// an `Arc` and the resulting mutex guard has no lifetime requirements.
419    #[cfg(feature = "arc_lock")]
420    #[inline]
421    pub fn try_lock_arc_until(
422        self: &Arc<Self>,
423        timeout: R::Instant,
424    ) -> Option<ArcMutexGuard<R, T>> {
425        if self.raw.try_lock_until(timeout) {
426            // SAFETY: locking guarantee is upheld
427            Some(unsafe { self.make_arc_guard_unchecked() })
428        } else {
429            None
430        }
431    }
432}
433
434impl<R: RawMutex, T: ?Sized + Default> Default for Mutex<R, T> {
435    #[inline]
436    fn default() -> Mutex<R, T> {
437        Mutex::new(Default::default())
438    }
439}
440
441impl<R: RawMutex, T> From<T> for Mutex<R, T> {
442    #[inline]
443    fn from(t: T) -> Mutex<R, T> {
444        Mutex::new(t)
445    }
446}
447
448impl<R: RawMutex, T: ?Sized + fmt::Debug> fmt::Debug for Mutex<R, T> {
449    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450        match self.try_lock() {
451            Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
452            None => {
453                struct LockedPlaceholder;
454                impl fmt::Debug for LockedPlaceholder {
455                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456                        f.write_str("<locked>")
457                    }
458                }
459
460                f.debug_struct("Mutex")
461                    .field("data", &LockedPlaceholder)
462                    .finish()
463            }
464        }
465    }
466}
467
468// Copied and modified from serde
469#[cfg(feature = "serde")]
470impl<R, T> Serialize for Mutex<R, T>
471where
472    R: RawMutex,
473    T: Serialize + ?Sized,
474{
475    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
476    where
477        S: Serializer,
478    {
479        self.lock().serialize(serializer)
480    }
481}
482
483#[cfg(feature = "serde")]
484impl<'de, R, T> Deserialize<'de> for Mutex<R, T>
485where
486    R: RawMutex,
487    T: Deserialize<'de> + ?Sized,
488{
489    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
490    where
491        D: Deserializer<'de>,
492    {
493        Deserialize::deserialize(deserializer).map(Mutex::new)
494    }
495}
496
497/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
498/// dropped (falls out of scope), the lock will be unlocked.
499///
500/// The data protected by the mutex can be accessed through this guard via its
501/// `Deref` and `DerefMut` implementations.
502#[clippy::has_significant_drop]
503#[must_use = "if unused the Mutex will immediately unlock"]
504pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> {
505    mutex: &'a Mutex<R, T>,
506    marker: PhantomData<(&'a mut T, R::GuardMarker)>,
507}
508
509unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {}
510
511impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
512    /// Returns a reference to the original `Mutex` object.
513    pub fn mutex(s: &Self) -> &'a Mutex<R, T> {
514        s.mutex
515    }
516
517    /// Makes a new `MappedMutexGuard` for a component of the locked data.
518    ///
519    /// This operation cannot fail as the `MutexGuard` passed
520    /// in already locked the mutex.
521    ///
522    /// This is an associated function that needs to be
523    /// used as `MutexGuard::map(...)`. A method would interfere with methods of
524    /// the same name on the contents of the locked data.
525    #[inline]
526    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
527    where
528        F: FnOnce(&mut T) -> &mut U,
529    {
530        let raw = &s.mutex.raw;
531        let data = f(unsafe { &mut *s.mutex.data.get() });
532        mem::forget(s);
533        MappedMutexGuard {
534            raw,
535            data,
536            marker: PhantomData,
537        }
538    }
539
540    /// Attempts to make a new `MappedMutexGuard` for a component of the
541    /// locked data. The original guard is returned if the closure returns `None`.
542    ///
543    /// This operation cannot fail as the `MutexGuard` passed
544    /// in already locked the mutex.
545    ///
546    /// This is an associated function that needs to be
547    /// used as `MutexGuard::try_map(...)`. A method would interfere with methods of
548    /// the same name on the contents of the locked data.
549    #[inline]
550    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
551    where
552        F: FnOnce(&mut T) -> Option<&mut U>,
553    {
554        let raw = &s.mutex.raw;
555        let data = match f(unsafe { &mut *s.mutex.data.get() }) {
556            Some(data) => data,
557            None => return Err(s),
558        };
559        mem::forget(s);
560        Ok(MappedMutexGuard {
561            raw,
562            data,
563            marker: PhantomData,
564        })
565    }
566
567    /// Temporarily unlocks the mutex to execute the given function.
568    ///
569    /// This is safe because `&mut` guarantees that there exist no other
570    /// references to the data protected by the mutex.
571    #[inline]
572    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
573    where
574        F: FnOnce() -> U,
575    {
576        // Safety: A MutexGuard always holds the lock.
577        unsafe {
578            s.mutex.raw.unlock();
579        }
580        defer!(s.mutex.raw.lock());
581        f()
582    }
583
584    /// Leaks the mutex guard and returns a mutable reference to the data
585    /// protected by the mutex.
586    ///
587    /// This will leave the `Mutex` in a locked state.
588    #[inline]
589    pub fn leak(s: Self) -> &'a mut T {
590        let r = unsafe { &mut *s.mutex.data.get() };
591        mem::forget(s);
592        r
593    }
594}
595
596impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
597    /// Unlocks the mutex using a fair unlock protocol.
598    ///
599    /// By default, mutexes are unfair and allow the current thread to re-lock
600    /// the mutex before another has the chance to acquire the lock, even if
601    /// that thread has been blocked on the mutex for a long time. This is the
602    /// default because it allows much higher throughput as it avoids forcing a
603    /// context switch on every mutex unlock. This can result in one thread
604    /// acquiring a mutex many more times than other threads.
605    ///
606    /// However in some cases it can be beneficial to ensure fairness by forcing
607    /// the lock to pass on to a waiting thread if there is one. This is done by
608    /// using this method instead of dropping the `MutexGuard` normally.
609    #[inline]
610    pub fn unlock_fair(s: Self) {
611        // Safety: A MutexGuard always holds the lock.
612        unsafe {
613            s.mutex.raw.unlock_fair();
614        }
615        mem::forget(s);
616    }
617
618    /// Temporarily unlocks the mutex to execute the given function.
619    ///
620    /// The mutex is unlocked using a fair unlock protocol.
621    ///
622    /// This is safe because `&mut` guarantees that there exist no other
623    /// references to the data protected by the mutex.
624    #[inline]
625    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
626    where
627        F: FnOnce() -> U,
628    {
629        // Safety: A MutexGuard always holds the lock.
630        unsafe {
631            s.mutex.raw.unlock_fair();
632        }
633        defer!(s.mutex.raw.lock());
634        f()
635    }
636
637    /// Temporarily yields the mutex to a waiting thread if there is one.
638    ///
639    /// This method is functionally equivalent to calling `unlock_fair` followed
640    /// by `lock`, however it can be much more efficient in the case where there
641    /// are no waiting threads.
642    #[inline]
643    pub fn bump(s: &mut Self) {
644        // Safety: A MutexGuard always holds the lock.
645        unsafe {
646            s.mutex.raw.bump();
647        }
648    }
649}
650
651impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> {
652    type Target = T;
653    #[inline]
654    fn deref(&self) -> &T {
655        unsafe { &*self.mutex.data.get() }
656    }
657}
658
659impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> {
660    #[inline]
661    fn deref_mut(&mut self) -> &mut T {
662        unsafe { &mut *self.mutex.data.get() }
663    }
664}
665
666impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> {
667    #[inline]
668    fn drop(&mut self) {
669        // Safety: A MutexGuard always holds the lock.
670        unsafe {
671            self.mutex.raw.unlock();
672        }
673    }
674}
675
676impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> {
677    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
678        fmt::Debug::fmt(&**self, f)
679    }
680}
681
682impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> {
683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
684        (**self).fmt(f)
685    }
686}
687
688#[cfg(feature = "owning_ref")]
689unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {}
690
691/// An RAII mutex guard returned by the `Arc` locking operations on `Mutex`.
692///
693/// This is similar to the `MutexGuard` struct, except instead of using a reference to unlock the `Mutex` it
694/// uses an `Arc<Mutex>`. This has several advantages, most notably that it has an `'static` lifetime.
695#[cfg(feature = "arc_lock")]
696#[clippy::has_significant_drop]
697#[must_use = "if unused the Mutex will immediately unlock"]
698pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> {
699    mutex: Arc<Mutex<R, T>>,
700    marker: PhantomData<*const ()>,
701}
702
703#[cfg(feature = "arc_lock")]
704unsafe impl<R: RawMutex + Send + Sync, T: Send + ?Sized> Send for ArcMutexGuard<R, T> where
705    R::GuardMarker: Send
706{
707}
708#[cfg(feature = "arc_lock")]
709unsafe impl<R: RawMutex + Sync, T: Sync + ?Sized> Sync for ArcMutexGuard<R, T> where
710    R::GuardMarker: Sync
711{
712}
713
714#[cfg(feature = "arc_lock")]
715impl<R: RawMutex, T: ?Sized> ArcMutexGuard<R, T> {
716    /// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`.
717    #[inline]
718    pub fn mutex(s: &Self) -> &Arc<Mutex<R, T>> {
719        &s.mutex
720    }
721
722    /// Unlocks the mutex and returns the `Arc` that was held by the [`ArcMutexGuard`].
723    #[inline]
724    pub fn into_arc(s: Self) -> Arc<Mutex<R, T>> {
725        // Safety: Skip our Drop impl and manually unlock the mutex.
726        let arc = unsafe { ptr::read(&s.mutex) };
727        mem::forget(s);
728        unsafe {
729            arc.raw.unlock();
730        }
731        arc
732    }
733
734    /// Temporarily unlocks the mutex to execute the given function.
735    ///
736    /// This is safe because `&mut` guarantees that there exist no other
737    /// references to the data protected by the mutex.
738    #[inline]
739    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
740    where
741        F: FnOnce() -> U,
742    {
743        // Safety: A MutexGuard always holds the lock.
744        unsafe {
745            s.mutex.raw.unlock();
746        }
747        defer!(s.mutex.raw.lock());
748        f()
749    }
750}
751
752#[cfg(feature = "arc_lock")]
753impl<R: RawMutexFair, T: ?Sized> ArcMutexGuard<R, T> {
754    /// Unlocks the mutex using a fair unlock protocol.
755    ///
756    /// This is functionally identical to the `unlock_fair` method on [`MutexGuard`].
757    #[inline]
758    pub fn unlock_fair(s: Self) {
759        // Safety: A MutexGuard always holds the lock.
760        unsafe {
761            s.mutex.raw.unlock_fair();
762        }
763
764        // SAFETY: make sure the Arc gets it reference decremented
765        let mut s = ManuallyDrop::new(s);
766        unsafe { ptr::drop_in_place(&mut s.mutex) };
767    }
768
769    /// Temporarily unlocks the mutex to execute the given function.
770    ///
771    /// This is functionally identical to the `unlocked_fair` method on [`MutexGuard`].
772    #[inline]
773    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
774    where
775        F: FnOnce() -> U,
776    {
777        // Safety: A MutexGuard always holds the lock.
778        unsafe {
779            s.mutex.raw.unlock_fair();
780        }
781        defer!(s.mutex.raw.lock());
782        f()
783    }
784
785    /// Temporarily yields the mutex to a waiting thread if there is one.
786    ///
787    /// This is functionally identical to the `bump` method on [`MutexGuard`].
788    #[inline]
789    pub fn bump(s: &mut Self) {
790        // Safety: A MutexGuard always holds the lock.
791        unsafe {
792            s.mutex.raw.bump();
793        }
794    }
795}
796
797#[cfg(feature = "arc_lock")]
798impl<R: RawMutex, T: ?Sized> Deref for ArcMutexGuard<R, T> {
799    type Target = T;
800    #[inline]
801    fn deref(&self) -> &T {
802        unsafe { &*self.mutex.data.get() }
803    }
804}
805
806#[cfg(feature = "arc_lock")]
807impl<R: RawMutex, T: ?Sized> DerefMut for ArcMutexGuard<R, T> {
808    #[inline]
809    fn deref_mut(&mut self) -> &mut T {
810        unsafe { &mut *self.mutex.data.get() }
811    }
812}
813
814#[cfg(feature = "arc_lock")]
815impl<R: RawMutex, T: ?Sized> Drop for ArcMutexGuard<R, T> {
816    #[inline]
817    fn drop(&mut self) {
818        // Safety: A MutexGuard always holds the lock.
819        unsafe {
820            self.mutex.raw.unlock();
821        }
822    }
823}
824
825/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a
826/// subfield of the protected data.
827///
828/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the
829/// former doesn't support temporarily unlocking and re-locking, since that
830/// could introduce soundness issues if the locked object is modified by another
831/// thread.
832#[clippy::has_significant_drop]
833#[must_use = "if unused the Mutex will immediately unlock"]
834pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> {
835    raw: &'a R,
836    data: *mut T,
837    marker: PhantomData<&'a mut T>,
838}
839
840unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync
841    for MappedMutexGuard<'a, R, T>
842{
843}
844unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + Send + 'a> Send for MappedMutexGuard<'a, R, T> where
845    R::GuardMarker: Send
846{
847}
848
849impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
850    /// Makes a new `MappedMutexGuard` for a component of the locked data.
851    ///
852    /// This operation cannot fail as the `MappedMutexGuard` passed
853    /// in already locked the mutex.
854    ///
855    /// This is an associated function that needs to be
856    /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of
857    /// the same name on the contents of the locked data.
858    #[inline]
859    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
860    where
861        F: FnOnce(&mut T) -> &mut U,
862    {
863        let raw = s.raw;
864        let data = f(unsafe { &mut *s.data });
865        mem::forget(s);
866        MappedMutexGuard {
867            raw,
868            data,
869            marker: PhantomData,
870        }
871    }
872
873    /// Attempts to make a new `MappedMutexGuard` for a component of the
874    /// locked data. The original guard is returned if the closure returns `None`.
875    ///
876    /// This operation cannot fail as the `MappedMutexGuard` passed
877    /// in already locked the mutex.
878    ///
879    /// This is an associated function that needs to be
880    /// used as `MappedMutexGuard::try_map(...)`. A method would interfere with methods of
881    /// the same name on the contents of the locked data.
882    #[inline]
883    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
884    where
885        F: FnOnce(&mut T) -> Option<&mut U>,
886    {
887        let raw = s.raw;
888        let data = match f(unsafe { &mut *s.data }) {
889            Some(data) => data,
890            None => return Err(s),
891        };
892        mem::forget(s);
893        Ok(MappedMutexGuard {
894            raw,
895            data,
896            marker: PhantomData,
897        })
898    }
899}
900
901impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
902    /// Unlocks the mutex using a fair unlock protocol.
903    ///
904    /// By default, mutexes are unfair and allow the current thread to re-lock
905    /// the mutex before another has the chance to acquire the lock, even if
906    /// that thread has been blocked on the mutex for a long time. This is the
907    /// default because it allows much higher throughput as it avoids forcing a
908    /// context switch on every mutex unlock. This can result in one thread
909    /// acquiring a mutex many more times than other threads.
910    ///
911    /// However in some cases it can be beneficial to ensure fairness by forcing
912    /// the lock to pass on to a waiting thread if there is one. This is done by
913    /// using this method instead of dropping the `MutexGuard` normally.
914    #[inline]
915    pub fn unlock_fair(s: Self) {
916        // Safety: A MutexGuard always holds the lock.
917        unsafe {
918            s.raw.unlock_fair();
919        }
920        mem::forget(s);
921    }
922}
923
924impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> {
925    type Target = T;
926    #[inline]
927    fn deref(&self) -> &T {
928        unsafe { &*self.data }
929    }
930}
931
932impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> {
933    #[inline]
934    fn deref_mut(&mut self) -> &mut T {
935        unsafe { &mut *self.data }
936    }
937}
938
939impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> {
940    #[inline]
941    fn drop(&mut self) {
942        // Safety: A MappedMutexGuard always holds the lock.
943        unsafe {
944            self.raw.unlock();
945        }
946    }
947}
948
949impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> {
950    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
951        fmt::Debug::fmt(&**self, f)
952    }
953}
954
955impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
956    for MappedMutexGuard<'a, R, T>
957{
958    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
959        (**self).fmt(f)
960    }
961}
962
963#[cfg(feature = "owning_ref")]
964unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {}