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