Skip to main content

lock_api/
remutex.rs

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