async_lock/
mutex.rs

1use core::borrow::Borrow;
2use core::cell::UnsafeCell;
3use core::fmt;
4use core::marker::{PhantomData, PhantomPinned};
5use core::ops::{Deref, DerefMut};
6use core::pin::Pin;
7use core::task::Poll;
8
9use alloc::sync::Arc;
10
11// We don't use loom::UnsafeCell as that doesn't work with the Mutex API.
12use crate::sync::atomic::{AtomicUsize, Ordering};
13
14#[cfg(all(feature = "std", not(target_family = "wasm")))]
15use std::time::{Duration, Instant};
16
17use event_listener::{Event, EventListener};
18use event_listener_strategy::{easy_wrapper, EventListenerFuture};
19
20/// An async mutex.
21///
22/// The locking mechanism uses eventual fairness to ensure locking will be fair on average without
23/// sacrificing performance. This is done by forcing a fair lock whenever a lock operation is
24/// starved for longer than 0.5 milliseconds.
25///
26/// # Examples
27///
28/// ```
29/// # futures_lite::future::block_on(async {
30/// use async_lock::Mutex;
31///
32/// let m = Mutex::new(1);
33///
34/// let mut guard = m.lock().await;
35/// *guard = 2;
36///
37/// assert!(m.try_lock().is_none());
38/// drop(guard);
39/// assert_eq!(*m.try_lock().unwrap(), 2);
40/// # })
41/// ```
42pub struct Mutex<T: ?Sized> {
43    /// Current state of the mutex.
44    ///
45    /// The least significant bit is set to 1 if the mutex is locked.
46    /// The other bits hold the number of starved lock operations.
47    state: AtomicUsize,
48
49    /// Lock operations waiting for the mutex to be released.
50    lock_ops: Event,
51
52    /// The value inside the mutex.
53    data: UnsafeCell<T>,
54}
55
56unsafe impl<T: Send + ?Sized> Send for Mutex<T> {}
57unsafe impl<T: Send + ?Sized> Sync for Mutex<T> {}
58
59impl<T> Mutex<T> {
60    const_fn! {
61        const_if: #[cfg(not(loom))];
62        /// Creates a new async mutex.
63        ///
64        /// # Examples
65        ///
66        /// ```
67        /// use async_lock::Mutex;
68        ///
69        /// let mutex = Mutex::new(0);
70        /// ```
71        pub const fn new(data: T) -> Mutex<T> {
72            Mutex {
73                state: AtomicUsize::new(0),
74                lock_ops: Event::new(),
75                data: UnsafeCell::new(data),
76            }
77        }
78    }
79
80    /// Consumes the mutex, returning the underlying data.
81    ///
82    /// # Examples
83    ///
84    /// ```
85    /// use async_lock::Mutex;
86    ///
87    /// let mutex = Mutex::new(10);
88    /// assert_eq!(mutex.into_inner(), 10);
89    /// ```
90    pub fn into_inner(self) -> T {
91        self.data.into_inner()
92    }
93}
94
95impl<T: ?Sized> Mutex<T> {
96    /// Acquires the mutex.
97    ///
98    /// Returns a guard that releases the mutex when dropped.
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// # futures_lite::future::block_on(async {
104    /// use async_lock::Mutex;
105    ///
106    /// let mutex = Mutex::new(10);
107    /// let guard = mutex.lock().await;
108    /// assert_eq!(*guard, 10);
109    /// # })
110    /// ```
111    #[inline]
112    pub fn lock(&self) -> Lock<'_, T> {
113        Lock::_new(LockInner {
114            mutex: self,
115            acquire_slow: None,
116        })
117    }
118
119    /// Acquires the mutex using the blocking strategy.
120    ///
121    /// Returns a guard that releases the mutex when dropped.
122    ///
123    /// # Blocking
124    ///
125    /// Rather than using asynchronous waiting, like the [`lock`][Mutex::lock] method,
126    /// this method will block the current thread until the lock is acquired.
127    ///
128    /// This method should not be used in an asynchronous context. It is intended to be
129    /// used in a way that a mutex can be used in both asynchronous and synchronous contexts.
130    /// Calling this method in an asynchronous context may result in a deadlock.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// use async_lock::Mutex;
136    ///
137    /// let mutex = Mutex::new(10);
138    /// let guard = mutex.lock_blocking();
139    /// assert_eq!(*guard, 10);
140    /// ```
141    #[cfg(all(feature = "std", not(target_family = "wasm")))]
142    #[inline]
143    pub fn lock_blocking(&self) -> MutexGuard<'_, T> {
144        self.lock().wait()
145    }
146
147    /// Attempts to acquire the mutex.
148    ///
149    /// If the mutex could not be acquired at this time, then [`None`] is returned. Otherwise, a
150    /// guard is returned that releases the mutex when dropped.
151    ///
152    /// # Examples
153    ///
154    /// ```
155    /// use async_lock::Mutex;
156    ///
157    /// let mutex = Mutex::new(10);
158    /// if let Some(guard) = mutex.try_lock() {
159    ///     assert_eq!(*guard, 10);
160    /// }
161    /// # ;
162    /// ```
163    #[inline]
164    pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
165        if self
166            .state
167            .compare_exchange(0, 1, Ordering::Acquire, Ordering::Acquire)
168            .is_ok()
169        {
170            Some(MutexGuard(self))
171        } else {
172            None
173        }
174    }
175
176    /// Returns a mutable reference to the underlying data.
177    ///
178    /// Since this call borrows the mutex mutably, no actual locking takes place -- the mutable
179    /// borrow statically guarantees the mutex is not already acquired.
180    ///
181    /// # Examples
182    ///
183    /// ```
184    /// # futures_lite::future::block_on(async {
185    /// use async_lock::Mutex;
186    ///
187    /// let mut mutex = Mutex::new(0);
188    /// *mutex.get_mut() = 10;
189    /// assert_eq!(*mutex.lock().await, 10);
190    /// # })
191    /// ```
192    pub fn get_mut(&mut self) -> &mut T {
193        self.data.get_mut()
194    }
195
196    /// Unlocks the mutex directly.
197    ///
198    /// # Safety
199    ///
200    /// This function is intended to be used only in the case where the mutex is locked,
201    /// and the guard is subsequently forgotten. Calling this while you don't hold a lock
202    /// on the mutex will likely lead to UB.
203    pub(crate) unsafe fn unlock_unchecked(&self) {
204        // Remove the last bit and notify a waiting lock operation.
205        self.state.fetch_sub(1, Ordering::Release);
206        self.lock_ops.notify(1);
207    }
208}
209
210impl<T: ?Sized> Mutex<T> {
211    /// Acquires the mutex and clones a reference to it.
212    ///
213    /// Returns an owned guard that releases the mutex when dropped.
214    ///
215    /// # Examples
216    ///
217    /// ```
218    /// # futures_lite::future::block_on(async {
219    /// use async_lock::Mutex;
220    /// use std::sync::Arc;
221    ///
222    /// let mutex = Arc::new(Mutex::new(10));
223    /// let guard = mutex.lock_arc().await;
224    /// assert_eq!(*guard, 10);
225    /// # })
226    /// ```
227    #[inline]
228    pub fn lock_arc(self: &Arc<Self>) -> LockArc<T> {
229        LockArc::_new(LockArcInnards::Unpolled {
230            mutex: Some(self.clone()),
231        })
232    }
233
234    /// Acquires the mutex and clones a reference to it using the blocking strategy.
235    ///
236    /// Returns an owned guard that releases the mutex when dropped.
237    ///
238    /// # Blocking
239    ///
240    /// Rather than using asynchronous waiting, like the [`lock_arc`][Mutex::lock_arc] method,
241    /// this method will block the current thread until the lock is acquired.
242    ///
243    /// This method should not be used in an asynchronous context. It is intended to be
244    /// used in a way that a mutex can be used in both asynchronous and synchronous contexts.
245    /// Calling this method in an asynchronous context may result in a deadlock.
246    ///
247    /// # Examples
248    ///
249    /// ```
250    /// use async_lock::Mutex;
251    /// use std::sync::Arc;
252    ///
253    /// let mutex = Arc::new(Mutex::new(10));
254    /// let guard = mutex.lock_arc_blocking();
255    /// assert_eq!(*guard, 10);
256    /// ```
257    #[cfg(all(feature = "std", not(target_family = "wasm")))]
258    #[inline]
259    pub fn lock_arc_blocking(self: &Arc<Self>) -> MutexGuardArc<T> {
260        self.lock_arc().wait()
261    }
262
263    /// Attempts to acquire the mutex and clone a reference to it.
264    ///
265    /// If the mutex could not be acquired at this time, then [`None`] is returned. Otherwise, an
266    /// owned guard is returned that releases the mutex when dropped.
267    ///
268    /// # Examples
269    ///
270    /// ```
271    /// use async_lock::Mutex;
272    /// use std::sync::Arc;
273    ///
274    /// let mutex = Arc::new(Mutex::new(10));
275    /// if let Some(guard) = mutex.try_lock() {
276    ///     assert_eq!(*guard, 10);
277    /// }
278    /// # ;
279    /// ```
280    #[inline]
281    pub fn try_lock_arc(self: &Arc<Self>) -> Option<MutexGuardArc<T>> {
282        if self
283            .state
284            .compare_exchange(0, 1, Ordering::Acquire, Ordering::Acquire)
285            .is_ok()
286        {
287            Some(MutexGuardArc(self.clone()))
288        } else {
289            None
290        }
291    }
292}
293
294impl<T: fmt::Debug + ?Sized> fmt::Debug for Mutex<T> {
295    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296        struct Locked;
297        impl fmt::Debug for Locked {
298            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299                f.write_str("<locked>")
300            }
301        }
302
303        match self.try_lock() {
304            None => f.debug_struct("Mutex").field("data", &Locked).finish(),
305            Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
306        }
307    }
308}
309
310impl<T> From<T> for Mutex<T> {
311    fn from(val: T) -> Mutex<T> {
312        Mutex::new(val)
313    }
314}
315
316impl<T: Default> Default for Mutex<T> {
317    fn default() -> Mutex<T> {
318        Mutex::new(Default::default())
319    }
320}
321
322easy_wrapper! {
323    /// The future returned by [`Mutex::lock`].
324    pub struct Lock<'a, T: ?Sized>(LockInner<'a, T> => MutexGuard<'a, T>);
325    #[cfg(all(feature = "std", not(target_family = "wasm")))]
326    pub(crate) wait();
327}
328
329pin_project_lite::pin_project! {
330    /// Inner future for acquiring the mutex.
331    struct LockInner<'a, T: ?Sized> {
332        // Reference to the mutex.
333        mutex: &'a Mutex<T>,
334
335        // The future that waits for the mutex to become available.
336        #[pin]
337        acquire_slow: Option<AcquireSlow<&'a Mutex<T>, T>>,
338    }
339}
340
341unsafe impl<T: Send + ?Sized> Send for Lock<'_, T> {}
342unsafe impl<T: Sync + ?Sized> Sync for Lock<'_, T> {}
343
344impl<T: ?Sized> fmt::Debug for Lock<'_, T> {
345    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346        f.write_str("Lock { .. }")
347    }
348}
349
350impl<'a, T: ?Sized> EventListenerFuture for LockInner<'a, T> {
351    type Output = MutexGuard<'a, T>;
352
353    #[inline]
354    fn poll_with_strategy<'x, S: event_listener_strategy::Strategy<'x>>(
355        self: Pin<&mut Self>,
356        strategy: &mut S,
357        context: &mut S::Context,
358    ) -> Poll<Self::Output> {
359        let mut this = self.project();
360
361        // This may seem weird, but the borrow checker complains otherwise.
362        if this.acquire_slow.is_none() {
363            match this.mutex.try_lock() {
364                Some(guard) => return Poll::Ready(guard),
365                None => {
366                    this.acquire_slow.set(Some(AcquireSlow::new(this.mutex)));
367                }
368            }
369        }
370
371        ready!(this
372            .acquire_slow
373            .as_pin_mut()
374            .unwrap()
375            .poll_with_strategy(strategy, context));
376        Poll::Ready(MutexGuard(this.mutex))
377    }
378}
379
380easy_wrapper! {
381    /// The future returned by [`Mutex::lock_arc`].
382    pub struct LockArc<T: ?Sized>(LockArcInnards<T> => MutexGuardArc<T>);
383    #[cfg(all(feature = "std", not(target_family = "wasm")))]
384    pub(crate) wait();
385}
386
387pin_project_lite::pin_project! {
388    #[project = LockArcInnardsProj]
389    enum LockArcInnards<T: ?Sized> {
390        /// We have not tried to poll the fast path yet.
391        Unpolled { mutex: Option<Arc<Mutex<T>>> },
392
393        /// We are acquiring the mutex through the slow path.
394        AcquireSlow {
395            #[pin]
396            inner: AcquireSlow<Arc<Mutex<T>>, T>
397        },
398    }
399}
400
401unsafe impl<T: Send + ?Sized> Send for LockArc<T> {}
402unsafe impl<T: Sync + ?Sized> Sync for LockArc<T> {}
403
404impl<T: ?Sized> fmt::Debug for LockArcInnards<T> {
405    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
406        f.write_str("LockArc { .. }")
407    }
408}
409
410impl<T: ?Sized> EventListenerFuture for LockArcInnards<T> {
411    type Output = MutexGuardArc<T>;
412
413    fn poll_with_strategy<'a, S: event_listener_strategy::Strategy<'a>>(
414        mut self: Pin<&mut Self>,
415        strategy: &mut S,
416        context: &mut S::Context,
417    ) -> Poll<Self::Output> {
418        // Set the inner future if needed.
419        if let LockArcInnardsProj::Unpolled { mutex } = self.as_mut().project() {
420            let mutex = mutex.take().expect("mutex taken more than once");
421
422            // Try the fast path before trying to register slowly.
423            if let Some(guard) = mutex.try_lock_arc() {
424                return Poll::Ready(guard);
425            }
426
427            // Set the inner future to the slow acquire path.
428            self.as_mut().set(LockArcInnards::AcquireSlow {
429                inner: AcquireSlow::new(mutex),
430            });
431        }
432
433        // Poll the inner future.
434        let value = match self.project() {
435            LockArcInnardsProj::AcquireSlow { inner } => {
436                ready!(inner.poll_with_strategy(strategy, context))
437            }
438            _ => unreachable!(),
439        };
440
441        Poll::Ready(MutexGuardArc(value))
442    }
443}
444
445pin_project_lite::pin_project! {
446    /// Future for acquiring the mutex slowly.
447    struct AcquireSlow<B: Borrow<Mutex<T>>, T: ?Sized> {
448        // Reference to the mutex.
449        mutex: Option<B>,
450
451        // The event listener waiting on the mutex.
452        listener: Option<EventListener>,
453
454        // The point at which the mutex lock was started.
455        start: Start,
456
457        // This lock operation is starving.
458        starved: bool,
459
460        // Capture the `T` lifetime.
461        #[pin]
462        _marker: PhantomData<T>,
463
464        // Keeping this type `!Unpin` enables future optimizations.
465        #[pin]
466        _pin: PhantomPinned
467    }
468
469    impl<T: ?Sized, B: Borrow<Mutex<T>>> PinnedDrop for AcquireSlow<B, T> {
470        fn drop(this: Pin<&mut Self>) {
471            // Make sure the starvation counter is decremented.
472            this.take_mutex();
473        }
474    }
475}
476
477/// `pin_project_lite` doesn't support `#[cfg]` yet, so we have to do this manually.
478struct Start {
479    #[cfg(all(feature = "std", not(target_family = "wasm")))]
480    start: Option<Instant>,
481}
482
483impl<T: ?Sized, B: Borrow<Mutex<T>>> AcquireSlow<B, T> {
484    /// Create a new `AcquireSlow` future.
485    #[cold]
486    fn new(mutex: B) -> Self {
487        AcquireSlow {
488            mutex: Some(mutex),
489            listener: None,
490            start: Start {
491                #[cfg(all(feature = "std", not(target_family = "wasm")))]
492                start: None,
493            },
494            starved: false,
495            _marker: PhantomData,
496            _pin: PhantomPinned,
497        }
498    }
499
500    /// Take the mutex reference out, decrementing the counter if necessary.
501    fn take_mutex(self: Pin<&mut Self>) -> Option<B> {
502        let this = self.project();
503        let mutex = this.mutex.take();
504
505        if *this.starved {
506            if let Some(mutex) = mutex.as_ref() {
507                // Decrement this counter before we exit.
508                mutex.borrow().state.fetch_sub(2, Ordering::Release);
509            }
510        }
511
512        mutex
513    }
514}
515
516impl<T: ?Sized, B: Unpin + Borrow<Mutex<T>>> EventListenerFuture for AcquireSlow<B, T> {
517    type Output = B;
518
519    #[cold]
520    fn poll_with_strategy<'a, S: event_listener_strategy::Strategy<'a>>(
521        mut self: Pin<&mut Self>,
522        strategy: &mut S,
523        context: &mut S::Context,
524    ) -> Poll<Self::Output> {
525        let this = self.as_mut().project();
526        #[cfg(all(feature = "std", not(target_family = "wasm")))]
527        let start = *this.start.start.get_or_insert_with(Instant::now);
528        let mutex = Borrow::<Mutex<T>>::borrow(
529            this.mutex.as_ref().expect("future polled after completion"),
530        );
531
532        // Only use this hot loop if we aren't currently starved.
533        if !*this.starved {
534            loop {
535                // Start listening for events.
536                if this.listener.is_none() {
537                    *this.listener = Some(mutex.lock_ops.listen());
538
539                    // Try locking if nobody is being starved.
540                    match mutex
541                        .state
542                        .compare_exchange(0, 1, Ordering::Acquire, Ordering::Acquire)
543                        .unwrap_or_else(|x| x)
544                    {
545                        // Lock acquired!
546                        0 => return Poll::Ready(self.take_mutex().unwrap()),
547
548                        // Lock is held and nobody is starved.
549                        1 => {}
550
551                        // Somebody is starved.
552                        _ => break,
553                    }
554                } else {
555                    ready!(strategy.poll(this.listener, context));
556
557                    // Try locking if nobody is being starved.
558                    match mutex
559                        .state
560                        .compare_exchange(0, 1, Ordering::Acquire, Ordering::Acquire)
561                        .unwrap_or_else(|x| x)
562                    {
563                        // Lock acquired!
564                        0 => return Poll::Ready(self.take_mutex().unwrap()),
565
566                        // Lock is held and nobody is starved.
567                        1 => {}
568
569                        // Somebody is starved.
570                        _ => {
571                            // Notify the first listener in line because we probably received a
572                            // notification that was meant for a starved task.
573                            mutex.lock_ops.notify(1);
574                            break;
575                        }
576                    }
577
578                    // If waiting for too long, fall back to a fairer locking strategy that will prevent
579                    // newer lock operations from starving us forever.
580                    #[cfg(all(feature = "std", not(target_family = "wasm")))]
581                    if start.elapsed() > Duration::from_micros(500) {
582                        break;
583                    }
584                }
585            }
586
587            // Increment the number of starved lock operations.
588            if mutex.state.fetch_add(2, Ordering::Release) > usize::MAX / 2 {
589                // In case of potential overflow, abort.
590                crate::abort();
591            }
592
593            // Indicate that we are now starving and will use a fairer locking strategy.
594            *this.starved = true;
595        }
596
597        // Fairer locking loop.
598        loop {
599            if this.listener.is_none() {
600                // Start listening for events.
601                *this.listener = Some(mutex.lock_ops.listen());
602
603                // Try locking if nobody else is being starved.
604                match mutex
605                    .state
606                    .compare_exchange(2, 2 | 1, Ordering::Acquire, Ordering::Acquire)
607                    .unwrap_or_else(|x| x)
608                {
609                    // Lock acquired!
610                    2 => return Poll::Ready(self.take_mutex().unwrap()),
611
612                    // Lock is held by someone.
613                    s if s % 2 == 1 => {}
614
615                    // Lock is available.
616                    _ => {
617                        // Be fair: notify the first listener and then go wait in line.
618                        mutex.lock_ops.notify(1);
619                    }
620                }
621            } else {
622                // Wait for a notification.
623                ready!(strategy.poll(this.listener, context));
624
625                // Try acquiring the lock without waiting for others.
626                if mutex.state.fetch_or(1, Ordering::Acquire) % 2 == 0 {
627                    return Poll::Ready(self.take_mutex().unwrap());
628                }
629            }
630        }
631    }
632}
633
634/// A guard that releases the mutex when dropped.
635#[clippy::has_significant_drop]
636pub struct MutexGuard<'a, T: ?Sized>(&'a Mutex<T>);
637
638unsafe impl<T: Send + ?Sized> Send for MutexGuard<'_, T> {}
639unsafe impl<T: Sync + ?Sized> Sync for MutexGuard<'_, T> {}
640
641impl<'a, T: ?Sized> MutexGuard<'a, T> {
642    /// Returns a reference to the mutex a guard came from.
643    ///
644    /// # Examples
645    ///
646    /// ```
647    /// # futures_lite::future::block_on(async {
648    /// use async_lock::{Mutex, MutexGuard};
649    ///
650    /// let mutex = Mutex::new(10i32);
651    /// let guard = mutex.lock().await;
652    /// dbg!(MutexGuard::source(&guard));
653    /// # })
654    /// ```
655    pub fn source(guard: &MutexGuard<'a, T>) -> &'a Mutex<T> {
656        guard.0
657    }
658}
659
660impl<T: ?Sized> Drop for MutexGuard<'_, T> {
661    #[inline]
662    fn drop(&mut self) {
663        // SAFETY: we are dropping the mutex guard, therefore unlocking the mutex.
664        unsafe {
665            self.0.unlock_unchecked();
666        }
667    }
668}
669
670impl<T: fmt::Debug + ?Sized> fmt::Debug for MutexGuard<'_, T> {
671    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
672        fmt::Debug::fmt(&**self, f)
673    }
674}
675
676impl<T: fmt::Display + ?Sized> fmt::Display for MutexGuard<'_, T> {
677    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
678        (**self).fmt(f)
679    }
680}
681
682impl<T: ?Sized> Deref for MutexGuard<'_, T> {
683    type Target = T;
684
685    fn deref(&self) -> &T {
686        unsafe { &*self.0.data.get() }
687    }
688}
689
690impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
691    fn deref_mut(&mut self) -> &mut T {
692        unsafe { &mut *self.0.data.get() }
693    }
694}
695
696/// An owned guard that releases the mutex when dropped.
697#[clippy::has_significant_drop]
698pub struct MutexGuardArc<T: ?Sized>(Arc<Mutex<T>>);
699
700unsafe impl<T: Send + ?Sized> Send for MutexGuardArc<T> {}
701unsafe impl<T: Sync + ?Sized> Sync for MutexGuardArc<T> {}
702
703impl<T: ?Sized> MutexGuardArc<T> {
704    /// Returns a reference to the mutex a guard came from.
705    ///
706    /// # Examples
707    ///
708    /// ```
709    /// # futures_lite::future::block_on(async {
710    /// use async_lock::{Mutex, MutexGuardArc};
711    /// use std::sync::Arc;
712    ///
713    /// let mutex = Arc::new(Mutex::new(10i32));
714    /// let guard = mutex.lock_arc().await;
715    /// dbg!(MutexGuardArc::source(&guard));
716    /// # })
717    /// ```
718    pub fn source(guard: &Self) -> &Arc<Mutex<T>>
719    where
720        // Required because `MutexGuardArc` implements `Sync` regardless of whether `T` is `Send`,
721        // but this method allows dropping `T` from a different thead than it was created in.
722        T: Send,
723    {
724        &guard.0
725    }
726}
727
728impl<T: ?Sized> Drop for MutexGuardArc<T> {
729    #[inline]
730    fn drop(&mut self) {
731        // SAFETY: we are dropping the mutex guard, therefore unlocking the mutex.
732        unsafe {
733            self.0.unlock_unchecked();
734        }
735    }
736}
737
738impl<T: fmt::Debug + ?Sized> fmt::Debug for MutexGuardArc<T> {
739    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
740        fmt::Debug::fmt(&**self, f)
741    }
742}
743
744impl<T: fmt::Display + ?Sized> fmt::Display for MutexGuardArc<T> {
745    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
746        (**self).fmt(f)
747    }
748}
749
750impl<T: ?Sized> Deref for MutexGuardArc<T> {
751    type Target = T;
752
753    fn deref(&self) -> &T {
754        unsafe { &*self.0.data.get() }
755    }
756}
757
758impl<T: ?Sized> DerefMut for MutexGuardArc<T> {
759    fn deref_mut(&mut self) -> &mut T {
760        unsafe { &mut *self.0.data.get() }
761    }
762}