async_lock/
rwlock.rs

1use core::cell::UnsafeCell;
2use core::fmt;
3use core::mem::{self, ManuallyDrop};
4use core::ops::{Deref, DerefMut};
5use core::ptr::{self, NonNull};
6
7use alloc::sync::Arc;
8
9pub(crate) mod futures;
10mod raw;
11
12use self::futures::{
13    Read, ReadArc, UpgradableRead, UpgradableReadArc, Upgrade, UpgradeArc, Write, WriteArc,
14};
15use self::raw::{RawRwLock, RawUpgrade};
16
17/// An async reader-writer lock.
18///
19/// This type of lock allows multiple readers or one writer at any point in time.
20///
21/// The locking strategy is write-preferring, which means writers are never starved.
22/// Releasing a write lock wakes the next blocked reader and the next blocked writer.
23///
24/// # Examples
25///
26/// ```
27/// # futures_lite::future::block_on(async {
28/// use async_lock::RwLock;
29///
30/// let lock = RwLock::new(5);
31///
32/// // Multiple read locks can be held at a time.
33/// let r1 = lock.read().await;
34/// let r2 = lock.read().await;
35/// assert_eq!(*r1, 5);
36/// assert_eq!(*r2, 5);
37/// drop((r1, r2));
38///
39/// // Only one write lock can be held at a time.
40/// let mut w = lock.write().await;
41/// *w += 1;
42/// assert_eq!(*w, 6);
43/// # })
44/// ```
45pub struct RwLock<T: ?Sized> {
46    /// The underlying locking implementation.
47    /// Doesn't depend on `T`.
48    raw: RawRwLock,
49
50    /// The inner value.
51    value: UnsafeCell<T>,
52}
53
54unsafe impl<T: Send + ?Sized> Send for RwLock<T> {}
55unsafe impl<T: Send + Sync + ?Sized> Sync for RwLock<T> {}
56
57impl<T> RwLock<T> {
58    const_fn! {
59        const_if: #[cfg(not(loom))];
60        /// Creates a new reader-writer lock.
61        ///
62        /// # Examples
63        ///
64        /// ```
65        /// use async_lock::RwLock;
66        ///
67        /// let lock = RwLock::new(0);
68        /// ```
69        #[must_use]
70        #[inline]
71        pub const fn new(t: T) -> RwLock<T> {
72            RwLock {
73                raw: RawRwLock::new(),
74                value: UnsafeCell::new(t),
75            }
76        }
77    }
78
79    /// Unwraps the lock and returns the inner value.
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// use async_lock::RwLock;
85    ///
86    /// let lock = RwLock::new(5);
87    /// assert_eq!(lock.into_inner(), 5);
88    /// ```
89    #[must_use]
90    #[inline]
91    pub fn into_inner(self) -> T {
92        self.value.into_inner()
93    }
94
95    /// Attempts to acquire an an owned, reference-counted read lock.
96    ///
97    /// If a read lock could not be acquired at this time, then [`None`] is returned. Otherwise, a
98    /// guard is returned that releases the lock when dropped.
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// # futures_lite::future::block_on(async {
104    /// use std::sync::Arc;
105    /// use async_lock::RwLock;
106    ///
107    /// let lock = Arc::new(RwLock::new(1));
108    ///
109    /// let reader = lock.read_arc().await;
110    /// assert_eq!(*reader, 1);
111    ///
112    /// assert!(lock.try_read_arc().is_some());
113    /// # })
114    /// ```
115    #[inline]
116    pub fn try_read_arc(self: &Arc<Self>) -> Option<RwLockReadGuardArc<T>> {
117        if self.raw.try_read() {
118            let arc = self.clone();
119
120            // SAFETY: we previously acquired a read lock.
121            Some(unsafe { RwLockReadGuardArc::from_arc(arc) })
122        } else {
123            None
124        }
125    }
126
127    /// Acquires an owned, reference-counted read lock.
128    ///
129    /// Returns a guard that releases the lock when dropped.
130    ///
131    /// Note that attempts to acquire a read lock will block if there are also concurrent attempts
132    /// to acquire a write lock.
133    ///
134    /// # Examples
135    ///
136    /// ```
137    /// # futures_lite::future::block_on(async {
138    /// use std::sync::Arc;
139    /// use async_lock::RwLock;
140    ///
141    /// let lock = Arc::new(RwLock::new(1));
142    ///
143    /// let reader = lock.read_arc().await;
144    /// assert_eq!(*reader, 1);
145    ///
146    /// assert!(lock.try_read_arc().is_some());
147    /// # })
148    /// ```
149    #[inline]
150    pub fn read_arc<'a>(self: &'a Arc<Self>) -> ReadArc<'a, T> {
151        ReadArc::new(self.raw.read(), self)
152    }
153
154    /// Acquires an owned, reference-counted read lock.
155    ///
156    /// Returns a guard that releases the lock when dropped.
157    ///
158    /// Note that attempts to acquire a read lock will block if there are also concurrent attempts
159    /// to acquire a write lock.
160    ///
161    /// # Blocking
162    ///
163    /// Rather than using asynchronous waiting, like the [`read_arc`][`RwLock::read_arc`] method,
164    /// this method will block the current thread until the read lock is acquired.
165    ///
166    /// This method should not be used in an asynchronous context. It is intended to be
167    /// used in a way that a lock can be used in both asynchronous and synchronous contexts.
168    /// Calling this method in an asynchronous context may result in a deadlock.
169    ///
170    /// # Examples
171    ///
172    /// ```
173    /// use std::sync::Arc;
174    /// use async_lock::RwLock;
175    ///
176    /// let lock = Arc::new(RwLock::new(1));
177    ///
178    /// let reader = lock.read_arc_blocking();
179    /// assert_eq!(*reader, 1);
180    ///
181    /// assert!(lock.try_read().is_some());
182    /// ```
183    #[cfg(all(feature = "std", not(target_family = "wasm")))]
184    #[inline]
185    pub fn read_arc_blocking(self: &Arc<Self>) -> RwLockReadGuardArc<T> {
186        self.read_arc().wait()
187    }
188}
189
190impl<T: ?Sized> RwLock<T> {
191    /// Attempts to acquire a read lock.
192    ///
193    /// If a read lock could not be acquired at this time, then [`None`] is returned. Otherwise, a
194    /// guard is returned that releases the lock when dropped.
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// # futures_lite::future::block_on(async {
200    /// use async_lock::RwLock;
201    ///
202    /// let lock = RwLock::new(1);
203    ///
204    /// let reader = lock.read().await;
205    /// assert_eq!(*reader, 1);
206    ///
207    /// assert!(lock.try_read().is_some());
208    /// # })
209    /// ```
210    #[inline]
211    pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
212        if self.raw.try_read() {
213            Some(RwLockReadGuard {
214                lock: &self.raw,
215                value: self.value.get(),
216            })
217        } else {
218            None
219        }
220    }
221
222    /// Acquires a read lock.
223    ///
224    /// Returns a guard that releases the lock when dropped.
225    ///
226    /// Note that attempts to acquire a read lock will block if there are also concurrent attempts
227    /// to acquire a write lock.
228    ///
229    /// # Examples
230    ///
231    /// ```
232    /// # futures_lite::future::block_on(async {
233    /// use async_lock::RwLock;
234    ///
235    /// let lock = RwLock::new(1);
236    ///
237    /// let reader = lock.read().await;
238    /// assert_eq!(*reader, 1);
239    ///
240    /// assert!(lock.try_read().is_some());
241    /// # })
242    /// ```
243    #[inline]
244    pub fn read(&self) -> Read<'_, T> {
245        Read::new(self.raw.read(), self.value.get())
246    }
247
248    /// Acquires a read lock.
249    ///
250    /// Returns a guard that releases the lock when dropped.
251    ///
252    /// Note that attempts to acquire a read lock will block if there are also concurrent attempts
253    /// to acquire a write lock.
254    ///
255    /// # Blocking
256    ///
257    /// Rather than using asynchronous waiting, like the [`read`][`RwLock::read`] method,
258    /// this method will block the current thread until the read lock is acquired.
259    ///
260    /// This method should not be used in an asynchronous context. It is intended to be
261    /// used in a way that a lock can be used in both asynchronous and synchronous contexts.
262    /// Calling this method in an asynchronous context may result in a deadlock.
263    ///
264    /// # Examples
265    ///
266    /// ```
267    /// use async_lock::RwLock;
268    ///
269    /// let lock = RwLock::new(1);
270    ///
271    /// let reader = lock.read_blocking();
272    /// assert_eq!(*reader, 1);
273    ///
274    /// assert!(lock.try_read().is_some());
275    /// ```
276    #[cfg(all(feature = "std", not(target_family = "wasm")))]
277    #[inline]
278    pub fn read_blocking(&self) -> RwLockReadGuard<'_, T> {
279        self.read().wait()
280    }
281
282    /// Attempts to acquire a read lock with the possiblity to upgrade to a write lock.
283    ///
284    /// If a read lock could not be acquired at this time, then [`None`] is returned. Otherwise, a
285    /// guard is returned that releases the lock when dropped.
286    ///
287    /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there
288    /// can be at most one upgradable read lock at a time.
289    ///
290    /// # Examples
291    ///
292    /// ```
293    /// # futures_lite::future::block_on(async {
294    /// use async_lock::{RwLock, RwLockUpgradableReadGuard};
295    ///
296    /// let lock = RwLock::new(1);
297    ///
298    /// let reader = lock.upgradable_read().await;
299    /// assert_eq!(*reader, 1);
300    /// assert_eq!(*lock.try_read().unwrap(), 1);
301    ///
302    /// let mut writer = RwLockUpgradableReadGuard::upgrade(reader).await;
303    /// *writer = 2;
304    /// # })
305    /// ```
306    #[inline]
307    pub fn try_upgradable_read(&self) -> Option<RwLockUpgradableReadGuard<'_, T>> {
308        if self.raw.try_upgradable_read() {
309            Some(RwLockUpgradableReadGuard {
310                lock: &self.raw,
311                value: self.value.get(),
312            })
313        } else {
314            None
315        }
316    }
317
318    /// Acquires a read lock with the possiblity to upgrade to a write lock.
319    ///
320    /// Returns a guard that releases the lock when dropped.
321    ///
322    /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there
323    /// can be at most one upgradable read lock at a time.
324    ///
325    /// Note that attempts to acquire an upgradable read lock will block if there are concurrent
326    /// attempts to acquire another upgradable read lock or a write lock.
327    ///
328    /// # Examples
329    ///
330    /// ```
331    /// # futures_lite::future::block_on(async {
332    /// use async_lock::{RwLock, RwLockUpgradableReadGuard};
333    ///
334    /// let lock = RwLock::new(1);
335    ///
336    /// let reader = lock.upgradable_read().await;
337    /// assert_eq!(*reader, 1);
338    /// assert_eq!(*lock.try_read().unwrap(), 1);
339    ///
340    /// let mut writer = RwLockUpgradableReadGuard::upgrade(reader).await;
341    /// *writer = 2;
342    /// # })
343    /// ```
344    #[inline]
345    pub fn upgradable_read(&self) -> UpgradableRead<'_, T> {
346        UpgradableRead::new(self.raw.upgradable_read(), self.value.get())
347    }
348
349    /// Attempts to acquire a read lock with the possiblity to upgrade to a write lock.
350    ///
351    /// Returns a guard that releases the lock when dropped.
352    ///
353    /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there
354    /// can be at most one upgradable read lock at a time.
355    ///
356    /// Note that attempts to acquire an upgradable read lock will block if there are concurrent
357    /// attempts to acquire another upgradable read lock or a write lock.
358    ///
359    /// # Blocking
360    ///
361    /// Rather than using asynchronous waiting, like the [`upgradable_read`][`RwLock::upgradable_read`]
362    /// method, this method will block the current thread until the read lock is acquired.
363    ///
364    /// This method should not be used in an asynchronous context. It is intended to be
365    /// used in a way that a lock can be used in both asynchronous and synchronous contexts.
366    /// Calling this method in an asynchronous context may result in a deadlock.
367    ///
368    /// # Examples
369    ///
370    /// ```
371    /// use async_lock::{RwLock, RwLockUpgradableReadGuard};
372    ///
373    /// let lock = RwLock::new(1);
374    ///
375    /// let reader = lock.upgradable_read_blocking();
376    /// assert_eq!(*reader, 1);
377    /// assert_eq!(*lock.try_read().unwrap(), 1);
378    ///
379    /// let mut writer = RwLockUpgradableReadGuard::upgrade_blocking(reader);
380    /// *writer = 2;
381    /// ```
382    #[cfg(all(feature = "std", not(target_family = "wasm")))]
383    #[inline]
384    pub fn upgradable_read_blocking(&self) -> RwLockUpgradableReadGuard<'_, T> {
385        self.upgradable_read().wait()
386    }
387
388    /// Attempts to acquire an owned, reference-counted read lock
389    /// with the possiblity to upgrade to a write lock.
390    ///
391    /// Returns a guard that releases the lock when dropped.
392    ///
393    /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there
394    /// can be at most one upgradable read lock at a time.
395    ///
396    /// Note that attempts to acquire an upgradable read lock will block if there are concurrent
397    /// attempts to acquire another upgradable read lock or a write lock.
398    ///
399    /// # Blocking
400    ///
401    /// Rather than using asynchronous waiting, like the [`upgradable_read_arc`][`RwLock::upgradable_read_arc`]
402    /// method, this method will block the current thread until the read lock is acquired.
403    ///
404    /// This method should not be used in an asynchronous context. It is intended to be
405    /// used in a way that a lock can be used in both asynchronous and synchronous contexts.
406    /// Calling this method in an asynchronous context may result in a deadlock.
407    ///
408    /// # Examples
409    ///
410    /// ```
411    /// use std::sync::Arc;
412    /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc};
413    ///
414    /// let lock = Arc::new(RwLock::new(1));
415    ///
416    /// let reader = lock.upgradable_read_arc_blocking();
417    /// assert_eq!(*reader, 1);
418    /// assert_eq!(*lock.try_read().unwrap(), 1);
419    ///
420    /// let mut writer = RwLockUpgradableReadGuardArc::upgrade_blocking(reader);
421    /// *writer = 2;
422    /// ```
423    #[cfg(all(feature = "std", not(target_family = "wasm")))]
424    #[inline]
425    pub fn upgradable_read_arc_blocking(self: &Arc<Self>) -> RwLockUpgradableReadGuardArc<T> {
426        self.upgradable_read_arc().wait()
427    }
428
429    /// Attempts to acquire an owned, reference-counted read lock with the possiblity to
430    /// upgrade to a write lock.
431    ///
432    /// If a read lock could not be acquired at this time, then [`None`] is returned. Otherwise, a
433    /// guard is returned that releases the lock when dropped.
434    ///
435    /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there
436    /// can be at most one upgradable read lock at a time.
437    ///
438    /// # Examples
439    ///
440    /// ```
441    /// # futures_lite::future::block_on(async {
442    /// use std::sync::Arc;
443    /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc};
444    ///
445    /// let lock = Arc::new(RwLock::new(1));
446    ///
447    /// let reader = lock.upgradable_read_arc().await;
448    /// assert_eq!(*reader, 1);
449    /// assert_eq!(*lock.try_read_arc().unwrap(), 1);
450    ///
451    /// let mut writer = RwLockUpgradableReadGuardArc::upgrade(reader).await;
452    /// *writer = 2;
453    /// # })
454    /// ```
455    #[inline]
456    pub fn try_upgradable_read_arc(self: &Arc<Self>) -> Option<RwLockUpgradableReadGuardArc<T>> {
457        if self.raw.try_upgradable_read() {
458            Some(RwLockUpgradableReadGuardArc { lock: self.clone() })
459        } else {
460            None
461        }
462    }
463
464    /// Acquires an owned, reference-counted read lock with the possiblity
465    /// to upgrade to a write lock.
466    ///
467    /// Returns a guard that releases the lock when dropped.
468    ///
469    /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there
470    /// can be at most one upgradable read lock at a time.
471    ///
472    /// Note that attempts to acquire an upgradable read lock will block if there are concurrent
473    /// attempts to acquire another upgradable read lock or a write lock.
474    ///
475    /// # Examples
476    ///
477    /// ```
478    /// # futures_lite::future::block_on(async {
479    /// use std::sync::Arc;
480    /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc};
481    ///
482    /// let lock = Arc::new(RwLock::new(1));
483    ///
484    /// let reader = lock.upgradable_read_arc().await;
485    /// assert_eq!(*reader, 1);
486    /// assert_eq!(*lock.try_read_arc().unwrap(), 1);
487    ///
488    /// let mut writer = RwLockUpgradableReadGuardArc::upgrade(reader).await;
489    /// *writer = 2;
490    /// # })
491    /// ```
492    #[inline]
493    pub fn upgradable_read_arc<'a>(self: &'a Arc<Self>) -> UpgradableReadArc<'a, T> {
494        UpgradableReadArc::new(self.raw.upgradable_read(), self)
495    }
496
497    /// Attempts to acquire a write lock.
498    ///
499    /// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise, a
500    /// guard is returned that releases the lock when dropped.
501    ///
502    /// # Examples
503    ///
504    /// ```
505    /// # futures_lite::future::block_on(async {
506    /// use async_lock::RwLock;
507    ///
508    /// let lock = RwLock::new(1);
509    ///
510    /// assert!(lock.try_write().is_some());
511    /// let reader = lock.read().await;
512    /// assert!(lock.try_write().is_none());
513    /// # })
514    /// ```
515    #[inline]
516    pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T>> {
517        if self.raw.try_write() {
518            Some(RwLockWriteGuard {
519                lock: &self.raw,
520                value: self.value.get(),
521            })
522        } else {
523            None
524        }
525    }
526
527    /// Acquires a write lock.
528    ///
529    /// Returns a guard that releases the lock when dropped.
530    ///
531    /// # Examples
532    ///
533    /// ```
534    /// # futures_lite::future::block_on(async {
535    /// use async_lock::RwLock;
536    ///
537    /// let lock = RwLock::new(1);
538    ///
539    /// let writer = lock.write().await;
540    /// assert!(lock.try_read().is_none());
541    /// # })
542    /// ```
543    #[inline]
544    pub fn write(&self) -> Write<'_, T> {
545        Write::new(self.raw.write(), self.value.get())
546    }
547
548    /// Acquires a write lock.
549    ///
550    /// Returns a guard that releases the lock when dropped.
551    ///
552    /// # Blocking
553    ///
554    /// Rather than using asynchronous waiting, like the [`write`] method, this method will
555    /// block the current thread until the write lock is acquired.
556    ///
557    /// This method should not be used in an asynchronous context. It is intended to be
558    /// used in a way that a lock can be used in both asynchronous and synchronous contexts.
559    /// Calling this method in an asynchronous context may result in a deadlock.
560    ///
561    /// # Examples
562    ///
563    /// ```
564    /// use async_lock::RwLock;
565    ///
566    /// let lock = RwLock::new(1);
567    ///
568    /// let writer = lock.write_blocking();
569    /// assert!(lock.try_read().is_none());
570    /// ```
571    #[cfg(all(feature = "std", not(target_family = "wasm")))]
572    #[inline]
573    pub fn write_blocking(&self) -> RwLockWriteGuard<'_, T> {
574        self.write().wait()
575    }
576
577    /// Attempts to acquire an owned, reference-counted write lock.
578    ///
579    /// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise, a
580    /// guard is returned that releases the lock when dropped.
581    ///
582    /// # Examples
583    ///
584    /// ```
585    /// # futures_lite::future::block_on(async {
586    /// use std::sync::Arc;
587    /// use async_lock::RwLock;
588    ///
589    /// let lock = Arc::new(RwLock::new(1));
590    ///
591    /// assert!(lock.try_write_arc().is_some());
592    /// let reader = lock.read_arc().await;
593    /// assert!(lock.try_write_arc().is_none());
594    /// # })
595    /// ```
596    #[inline]
597    pub fn try_write_arc(self: &Arc<Self>) -> Option<RwLockWriteGuardArc<T>> {
598        if self.raw.try_write() {
599            Some(RwLockWriteGuardArc { lock: self.clone() })
600        } else {
601            None
602        }
603    }
604
605    /// Acquires an owned, reference-counted write lock.
606    ///
607    /// Returns a guard that releases the lock when dropped.
608    ///
609    /// # Examples
610    ///
611    /// ```
612    /// # futures_lite::future::block_on(async {
613    /// use std::sync::Arc;
614    /// use async_lock::RwLock;
615    ///
616    /// let lock = Arc::new(RwLock::new(1));
617    ///
618    /// let writer = lock.write_arc().await;
619    /// assert!(lock.try_read_arc().is_none());
620    /// # })
621    /// ```
622    #[inline]
623    pub fn write_arc<'a>(self: &'a Arc<Self>) -> WriteArc<'a, T> {
624        WriteArc::new(self.raw.write(), self)
625    }
626
627    /// Acquires an owned, reference-counted write lock.
628    ///
629    /// Returns a guard that releases the lock when dropped.
630    ///
631    /// # Blocking
632    ///
633    /// Rather than using asynchronous waiting, like the [`write_arc`][RwLock::write_arc] method, this method will
634    /// block the current thread until the write lock is acquired.
635    ///
636    /// This method should not be used in an asynchronous context. It is intended to be
637    /// used in a way that a lock can be used in both asynchronous and synchronous contexts.
638    /// Calling this method in an asynchronous context may result in a deadlock.
639    ///
640    /// # Examples
641    ///
642    /// ```
643    /// use std::sync::Arc;
644    /// use async_lock::RwLock;
645    ///
646    /// let lock = Arc::new(RwLock::new(1));
647    ///
648    /// let writer = lock.write_arc_blocking();
649    /// assert!(lock.try_read().is_none());
650    /// ```
651    #[cfg(all(feature = "std", not(target_family = "wasm")))]
652    #[inline]
653    pub fn write_arc_blocking(self: &Arc<Self>) -> RwLockWriteGuardArc<T> {
654        self.write_arc().wait()
655    }
656
657    /// Returns a mutable reference to the inner value.
658    ///
659    /// Since this call borrows the lock mutably, no actual locking takes place. The mutable borrow
660    /// statically guarantees no locks exist.
661    ///
662    /// # Examples
663    ///
664    /// ```
665    /// # futures_lite::future::block_on(async {
666    /// use async_lock::RwLock;
667    ///
668    /// let mut lock = RwLock::new(1);
669    ///
670    /// *lock.get_mut() = 2;
671    /// assert_eq!(*lock.read().await, 2);
672    /// # })
673    /// ```
674    #[must_use]
675    #[inline]
676    pub fn get_mut(&mut self) -> &mut T {
677        unsafe { &mut *self.value.get() }
678    }
679}
680
681impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLock<T> {
682    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
683        struct Locked;
684        impl fmt::Debug for Locked {
685            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
686                f.write_str("<locked>")
687            }
688        }
689
690        match self.try_read() {
691            None => f.debug_struct("RwLock").field("value", &Locked).finish(),
692            Some(guard) => f.debug_struct("RwLock").field("value", &&*guard).finish(),
693        }
694    }
695}
696
697impl<T> From<T> for RwLock<T> {
698    #[inline]
699    fn from(val: T) -> RwLock<T> {
700        RwLock::new(val)
701    }
702}
703
704impl<T: Default + ?Sized> Default for RwLock<T> {
705    #[inline]
706    fn default() -> RwLock<T> {
707        RwLock::new(Default::default())
708    }
709}
710
711/// A guard that releases the read lock when dropped.
712#[clippy::has_significant_drop]
713pub struct RwLockReadGuard<'a, T: ?Sized> {
714    /// Reference to underlying locking implementation.
715    /// Doesn't depend on `T`.
716    lock: &'a RawRwLock,
717
718    /// Pointer to the value protected by the lock. Covariant in `T`.
719    value: *const T,
720}
721
722unsafe impl<T: Sync + ?Sized> Send for RwLockReadGuard<'_, T> {}
723unsafe impl<T: Sync + ?Sized> Sync for RwLockReadGuard<'_, T> {}
724
725impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
726    #[inline]
727    fn drop(&mut self) {
728        // SAFETY: we are dropping a read guard.
729        unsafe {
730            self.lock.read_unlock();
731        }
732    }
733}
734
735impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockReadGuard<'_, T> {
736    #[inline]
737    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
738        fmt::Debug::fmt(&**self, f)
739    }
740}
741
742impl<T: fmt::Display + ?Sized> fmt::Display for RwLockReadGuard<'_, T> {
743    #[inline]
744    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
745        (**self).fmt(f)
746    }
747}
748
749impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
750    type Target = T;
751
752    #[inline]
753    fn deref(&self) -> &T {
754        unsafe { &*self.value }
755    }
756}
757
758/// An owned, reference-counting guard that releases the read lock when dropped.
759#[clippy::has_significant_drop]
760pub struct RwLockReadGuardArc<T> {
761    /// **WARNING**: This doesn't actually point to a `T`!
762    /// It points to a `RwLock<T>`, via a pointer obtained with `Arc::into_raw`.
763    /// We lie for covariance.
764    lock: NonNull<T>,
765}
766
767unsafe impl<T: Send + Sync> Send for RwLockReadGuardArc<T> {}
768unsafe impl<T: Send + Sync> Sync for RwLockReadGuardArc<T> {}
769
770impl<T> RwLockReadGuardArc<T> {
771    /// Constructs the underlying `Arc` back from the underlying `RwLock`.
772    ///
773    /// # Safety
774    ///
775    /// Both the returned `Arc` and the guard will decrement their reference
776    /// counts on drop! So one of the two must be forgotten.
777    #[inline]
778    unsafe fn inner_arc(guard: &Self) -> ManuallyDrop<Arc<RwLock<T>>> {
779        ManuallyDrop::new(Arc::from_raw(guard.lock.as_ptr().cast()))
780    }
781
782    /// Constructs a guard from the underlying `Arc`.
783    ///
784    /// # Safety
785    ///
786    /// A read lock must be acquired before calling this.
787    #[inline]
788    unsafe fn from_arc(arc: Arc<RwLock<T>>) -> Self {
789        let ptr = Arc::into_raw(arc);
790
791        Self {
792            lock: NonNull::new(ptr as *mut RwLock<T> as *mut T).unwrap(),
793        }
794    }
795}
796
797impl<T> Drop for RwLockReadGuardArc<T> {
798    #[inline]
799    fn drop(&mut self) {
800        // SAFETY: we are in `drop`, decrementing the reference count
801        // on purpose.
802        // We hold a read lock on the `RwLock`.
803        unsafe {
804            let arc = ManuallyDrop::into_inner(Self::inner_arc(self));
805            arc.raw.read_unlock();
806        }
807    }
808}
809
810impl<T: fmt::Debug> fmt::Debug for RwLockReadGuardArc<T> {
811    #[inline]
812    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
813        fmt::Debug::fmt(&**self, f)
814    }
815}
816
817impl<T: fmt::Display> fmt::Display for RwLockReadGuardArc<T> {
818    #[inline]
819    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
820        (**self).fmt(f)
821    }
822}
823
824impl<T> Deref for RwLockReadGuardArc<T> {
825    type Target = T;
826
827    #[inline]
828    fn deref(&self) -> &T {
829        // SAFETY: we use `ManuallyDrop` to avoid double-drop.
830        // We hold a read lock on the `RwLock`.
831        unsafe {
832            let arc = Self::inner_arc(self);
833            &*arc.value.get()
834        }
835    }
836}
837
838/// A guard that releases the upgradable read lock when dropped.
839#[clippy::has_significant_drop]
840pub struct RwLockUpgradableReadGuard<'a, T: ?Sized> {
841    /// Reference to underlying locking implementation.
842    /// Doesn't depend on `T`.
843    /// This guard holds a lock on the witer mutex!
844    lock: &'a RawRwLock,
845
846    /// Pointer to the value protected by the lock. Invariant in `T`
847    /// as the upgradable lock could provide write access.
848    value: *mut T,
849}
850
851impl<'a, T: ?Sized> Drop for RwLockUpgradableReadGuard<'a, T> {
852    #[inline]
853    fn drop(&mut self) {
854        // SAFETY: we are dropping an upgradable read guard.
855        unsafe {
856            self.lock.upgradable_read_unlock();
857        }
858    }
859}
860
861unsafe impl<T: Send + Sync + ?Sized> Send for RwLockUpgradableReadGuard<'_, T> {}
862unsafe impl<T: Sync + ?Sized> Sync for RwLockUpgradableReadGuard<'_, T> {}
863
864impl<'a, T: ?Sized> RwLockUpgradableReadGuard<'a, T> {
865    /// Downgrades into a regular reader guard.
866    ///
867    /// # Examples
868    ///
869    /// ```
870    /// # futures_lite::future::block_on(async {
871    /// use async_lock::{RwLock, RwLockUpgradableReadGuard};
872    ///
873    /// let lock = RwLock::new(1);
874    ///
875    /// let reader = lock.upgradable_read().await;
876    /// assert_eq!(*reader, 1);
877    ///
878    /// assert!(lock.try_upgradable_read().is_none());
879    ///
880    /// let reader = RwLockUpgradableReadGuard::downgrade(reader);
881    ///
882    /// assert!(lock.try_upgradable_read().is_some());
883    /// # })
884    /// ```
885    #[inline]
886    pub fn downgrade(guard: Self) -> RwLockReadGuard<'a, T> {
887        let upgradable = ManuallyDrop::new(guard);
888
889        // SAFETY: `guard` is an upgradable read lock.
890        unsafe {
891            upgradable.lock.downgrade_upgradable_read();
892        };
893
894        RwLockReadGuard {
895            lock: upgradable.lock,
896            value: upgradable.value,
897        }
898    }
899
900    /// Attempts to upgrade into a write lock.
901    ///
902    /// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise,
903    /// an upgraded guard is returned that releases the write lock when dropped.
904    ///
905    /// This function can only fail if there are other active read locks.
906    ///
907    /// # Examples
908    ///
909    /// ```
910    /// # futures_lite::future::block_on(async {
911    /// use async_lock::{RwLock, RwLockUpgradableReadGuard};
912    ///
913    /// let lock = RwLock::new(1);
914    ///
915    /// let reader = lock.upgradable_read().await;
916    /// assert_eq!(*reader, 1);
917    ///
918    /// let reader2 = lock.read().await;
919    /// let reader = RwLockUpgradableReadGuard::try_upgrade(reader).unwrap_err();
920    ///
921    /// drop(reader2);
922    /// let writer = RwLockUpgradableReadGuard::try_upgrade(reader).unwrap();
923    /// # })
924    /// ```
925    #[inline]
926    pub fn try_upgrade(guard: Self) -> Result<RwLockWriteGuard<'a, T>, Self> {
927        // If there are no readers, grab the write lock.
928        // SAFETY: `guard` is an upgradable read guard
929        if unsafe { guard.lock.try_upgrade() } {
930            let reader = ManuallyDrop::new(guard);
931
932            Ok(RwLockWriteGuard {
933                lock: reader.lock,
934                value: reader.value,
935            })
936        } else {
937            Err(guard)
938        }
939    }
940
941    /// Upgrades into a write lock.
942    ///
943    /// # Examples
944    ///
945    /// ```
946    /// # futures_lite::future::block_on(async {
947    /// use async_lock::{RwLock, RwLockUpgradableReadGuard};
948    ///
949    /// let lock = RwLock::new(1);
950    ///
951    /// let reader = lock.upgradable_read().await;
952    /// assert_eq!(*reader, 1);
953    ///
954    /// let mut writer = RwLockUpgradableReadGuard::upgrade(reader).await;
955    /// *writer = 2;
956    /// # })
957    /// ```
958    #[inline]
959    pub fn upgrade(guard: Self) -> Upgrade<'a, T> {
960        let reader = ManuallyDrop::new(guard);
961
962        Upgrade::new(
963            // SAFETY: `reader` is an upgradable read guard
964            unsafe { reader.lock.upgrade() },
965            reader.value,
966        )
967    }
968
969    /// Upgrades into a write lock.
970    ///
971    /// # Blocking
972    ///
973    /// This function will block the current thread until it is able to acquire the write lock.
974    ///
975    /// # Examples
976    ///
977    /// ```
978    /// use async_lock::{RwLock, RwLockUpgradableReadGuard};
979    ///
980    /// let lock = RwLock::new(1);
981    ///
982    /// let reader = lock.upgradable_read_blocking();
983    /// assert_eq!(*reader, 1);
984    ///
985    /// let mut writer = RwLockUpgradableReadGuard::upgrade_blocking(reader);
986    /// *writer = 2;
987    /// ```
988    #[cfg(all(feature = "std", not(target_family = "wasm")))]
989    #[inline]
990    pub fn upgrade_blocking(guard: Self) -> RwLockWriteGuard<'a, T> {
991        RwLockUpgradableReadGuard::upgrade(guard).wait()
992    }
993}
994
995impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockUpgradableReadGuard<'_, T> {
996    #[inline]
997    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
998        fmt::Debug::fmt(&**self, f)
999    }
1000}
1001
1002impl<T: fmt::Display + ?Sized> fmt::Display for RwLockUpgradableReadGuard<'_, T> {
1003    #[inline]
1004    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1005        (**self).fmt(f)
1006    }
1007}
1008
1009impl<T: ?Sized> Deref for RwLockUpgradableReadGuard<'_, T> {
1010    type Target = T;
1011
1012    #[inline]
1013    fn deref(&self) -> &T {
1014        unsafe { &*self.value }
1015    }
1016}
1017
1018/// An owned, reference-counting guard that releases the upgradable read lock when dropped.
1019#[clippy::has_significant_drop]
1020pub struct RwLockUpgradableReadGuardArc<T: ?Sized> {
1021    /// We want invariance, so no need for pointer tricks.
1022    lock: Arc<RwLock<T>>,
1023}
1024
1025impl<T: ?Sized> Drop for RwLockUpgradableReadGuardArc<T> {
1026    #[inline]
1027    fn drop(&mut self) {
1028        // SAFETY: we are dropping an upgradable read guard.
1029        unsafe {
1030            self.lock.raw.upgradable_read_unlock();
1031        }
1032    }
1033}
1034
1035unsafe impl<T: Send + Sync + ?Sized> Send for RwLockUpgradableReadGuardArc<T> {}
1036unsafe impl<T: Send + Sync + ?Sized> Sync for RwLockUpgradableReadGuardArc<T> {}
1037
1038impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockUpgradableReadGuardArc<T> {
1039    #[inline]
1040    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1041        fmt::Debug::fmt(&**self, f)
1042    }
1043}
1044
1045impl<T: fmt::Display + ?Sized> fmt::Display for RwLockUpgradableReadGuardArc<T> {
1046    #[inline]
1047    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1048        (**self).fmt(f)
1049    }
1050}
1051
1052impl<T: ?Sized> Deref for RwLockUpgradableReadGuardArc<T> {
1053    type Target = T;
1054
1055    #[inline]
1056    fn deref(&self) -> &T {
1057        unsafe { &*self.lock.value.get() }
1058    }
1059}
1060
1061impl<T> RwLockUpgradableReadGuardArc<T> {
1062    /// Downgrades into a regular reader guard.
1063    ///
1064    /// # Examples
1065    ///
1066    /// ```
1067    /// # futures_lite::future::block_on(async {
1068    /// use std::sync::Arc;
1069    /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc};
1070    ///
1071    /// let lock = Arc::new(RwLock::new(1));
1072    ///
1073    /// let reader = lock.upgradable_read_arc().await;
1074    /// assert_eq!(*reader, 1);
1075    ///
1076    /// assert!(lock.try_upgradable_read_arc().is_none());
1077    ///
1078    /// let reader = RwLockUpgradableReadGuardArc::downgrade(reader);
1079    ///
1080    /// assert!(lock.try_upgradable_read_arc().is_some());
1081    /// # })
1082    /// ```
1083    #[inline]
1084    pub fn downgrade(guard: Self) -> RwLockReadGuardArc<T> {
1085        // SAFETY: we hold an upgradable read lock, which we are downgrading.
1086        unsafe {
1087            guard.lock.raw.downgrade_upgradable_read();
1088        }
1089
1090        // SAFETY: we just downgraded to a read lock.
1091        unsafe { RwLockReadGuardArc::from_arc(Self::into_arc(guard)) }
1092    }
1093}
1094
1095impl<T: ?Sized> RwLockUpgradableReadGuardArc<T> {
1096    /// Consumes the lock (without dropping) and returns the underlying `Arc`.
1097    #[inline]
1098    fn into_arc(guard: Self) -> Arc<RwLock<T>> {
1099        let guard = ManuallyDrop::new(guard);
1100        // SAFETY: `guard` is not used after this
1101        unsafe { ptr::read(&guard.lock) }
1102    }
1103
1104    /// Attempts to upgrade into a write lock.
1105    ///
1106    /// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise,
1107    /// an upgraded guard is returned that releases the write lock when dropped.
1108    ///
1109    /// This function can only fail if there are other active read locks.
1110    ///
1111    /// # Examples
1112    ///
1113    /// ```
1114    /// # futures_lite::future::block_on(async {
1115    /// use std::sync::Arc;
1116    /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc};
1117    ///
1118    /// let lock = Arc::new(RwLock::new(1));
1119    ///
1120    /// let reader = lock.upgradable_read_arc().await;
1121    /// assert_eq!(*reader, 1);
1122    ///
1123    /// let reader2 = lock.read_arc().await;
1124    /// let reader = RwLockUpgradableReadGuardArc::try_upgrade(reader).unwrap_err();
1125    ///
1126    /// drop(reader2);
1127    /// let writer = RwLockUpgradableReadGuardArc::try_upgrade(reader).unwrap();
1128    /// # })
1129    /// ```
1130    #[inline]
1131    pub fn try_upgrade(guard: Self) -> Result<RwLockWriteGuardArc<T>, Self> {
1132        // SAFETY: We hold an upgradable read guard.
1133        if unsafe { guard.lock.raw.try_upgrade() } {
1134            Ok(RwLockWriteGuardArc {
1135                lock: Self::into_arc(guard),
1136            })
1137        } else {
1138            Err(guard)
1139        }
1140    }
1141
1142    /// Upgrades into a write lock.
1143    ///
1144    /// # Examples
1145    ///
1146    /// ```
1147    /// # futures_lite::future::block_on(async {
1148    /// use std::sync::Arc;
1149    /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc};
1150    ///
1151    /// let lock = Arc::new(RwLock::new(1));
1152    ///
1153    /// let reader = lock.upgradable_read_arc().await;
1154    /// assert_eq!(*reader, 1);
1155    ///
1156    /// let mut writer = RwLockUpgradableReadGuardArc::upgrade(reader).await;
1157    /// *writer = 2;
1158    /// # })
1159    /// ```
1160    #[inline]
1161    pub fn upgrade(guard: Self) -> UpgradeArc<T> {
1162        // We need to do some ugly lying about lifetimes;
1163        // See the comment on the `raw` field of `ArcUpgrade`
1164        // for an explanation.
1165
1166        // SAFETY: we hold an upgradable read guard.
1167        let raw: RawUpgrade<'_> = unsafe { guard.lock.raw.upgrade() };
1168
1169        // SAFETY: see above explanation.
1170        let raw: RawUpgrade<'static> = unsafe { mem::transmute(raw) };
1171
1172        unsafe {
1173            UpgradeArc::new(
1174                ManuallyDrop::new(raw),
1175                ManuallyDrop::new(Self::into_arc(guard)),
1176            )
1177        }
1178    }
1179
1180    /// Upgrades into a write lock.
1181    ///
1182    /// # Blocking
1183    ///
1184    /// This function will block the current thread until it is able to acquire the write lock.
1185    ///
1186    /// # Examples
1187    ///
1188    /// ```
1189    /// use std::sync::Arc;
1190    /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc};
1191    ///
1192    /// let lock = Arc::new(RwLock::new(1));
1193    ///
1194    /// let reader = lock.upgradable_read_arc_blocking();
1195    /// assert_eq!(*reader, 1);
1196    ///
1197    /// let mut writer = RwLockUpgradableReadGuardArc::upgrade_blocking(reader);
1198    /// *writer = 2;
1199    /// ```
1200    #[cfg(all(feature = "std", not(target_family = "wasm")))]
1201    #[inline]
1202    pub fn upgrade_blocking(guard: Self) -> RwLockWriteGuardArc<T> {
1203        RwLockUpgradableReadGuardArc::upgrade(guard).wait()
1204    }
1205}
1206
1207/// A guard that releases the write lock when dropped.
1208#[clippy::has_significant_drop]
1209pub struct RwLockWriteGuard<'a, T: ?Sized> {
1210    /// Reference to underlying locking implementation.
1211    /// Doesn't depend on `T`.
1212    /// This guard holds a lock on the witer mutex!
1213    lock: &'a RawRwLock,
1214
1215    /// Pointer to the value protected by the lock. Invariant in `T`.
1216    value: *mut T,
1217}
1218
1219unsafe impl<T: Send + ?Sized> Send for RwLockWriteGuard<'_, T> {}
1220unsafe impl<T: Sync + ?Sized> Sync for RwLockWriteGuard<'_, T> {}
1221
1222impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
1223    #[inline]
1224    fn drop(&mut self) {
1225        // SAFETY: we are dropping a write lock
1226        unsafe {
1227            self.lock.write_unlock();
1228        }
1229    }
1230}
1231
1232impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
1233    /// Downgrades into a regular reader guard.
1234    ///
1235    /// # Examples
1236    ///
1237    /// ```
1238    /// # futures_lite::future::block_on(async {
1239    /// use async_lock::{RwLock, RwLockWriteGuard};
1240    ///
1241    /// let lock = RwLock::new(1);
1242    ///
1243    /// let mut writer = lock.write().await;
1244    /// *writer += 1;
1245    ///
1246    /// assert!(lock.try_read().is_none());
1247    ///
1248    /// let reader = RwLockWriteGuard::downgrade(writer);
1249    /// assert_eq!(*reader, 2);
1250    ///
1251    /// assert!(lock.try_read().is_some());
1252    /// # })
1253    /// ```
1254    #[inline]
1255    pub fn downgrade(guard: Self) -> RwLockReadGuard<'a, T> {
1256        let write = ManuallyDrop::new(guard);
1257
1258        // SAFETY: `write` is a write guard
1259        unsafe {
1260            write.lock.downgrade_write();
1261        }
1262
1263        RwLockReadGuard {
1264            lock: write.lock,
1265            value: write.value,
1266        }
1267    }
1268
1269    /// Downgrades into an upgradable reader guard.
1270    ///
1271    /// # Examples
1272    ///
1273    /// ```
1274    /// # futures_lite::future::block_on(async {
1275    /// use async_lock::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard};
1276    ///
1277    /// let lock = RwLock::new(1);
1278    ///
1279    /// let mut writer = lock.write().await;
1280    /// *writer += 1;
1281    ///
1282    /// assert!(lock.try_read().is_none());
1283    ///
1284    /// let reader = RwLockWriteGuard::downgrade_to_upgradable(writer);
1285    /// assert_eq!(*reader, 2);
1286    ///
1287    /// assert!(lock.try_write().is_none());
1288    /// assert!(lock.try_read().is_some());
1289    ///
1290    /// assert!(RwLockUpgradableReadGuard::try_upgrade(reader).is_ok())
1291    /// # })
1292    /// ```
1293    #[inline]
1294    pub fn downgrade_to_upgradable(guard: Self) -> RwLockUpgradableReadGuard<'a, T> {
1295        let write = ManuallyDrop::new(guard);
1296
1297        // SAFETY: `write` is a write guard
1298        unsafe {
1299            write.lock.downgrade_to_upgradable();
1300        }
1301
1302        RwLockUpgradableReadGuard {
1303            lock: write.lock,
1304            value: write.value,
1305        }
1306    }
1307}
1308
1309impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockWriteGuard<'_, T> {
1310    #[inline]
1311    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1312        fmt::Debug::fmt(&**self, f)
1313    }
1314}
1315
1316impl<T: fmt::Display + ?Sized> fmt::Display for RwLockWriteGuard<'_, T> {
1317    #[inline]
1318    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1319        (**self).fmt(f)
1320    }
1321}
1322
1323impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
1324    type Target = T;
1325
1326    #[inline]
1327    fn deref(&self) -> &T {
1328        unsafe { &*self.value }
1329    }
1330}
1331
1332impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
1333    #[inline]
1334    fn deref_mut(&mut self) -> &mut T {
1335        unsafe { &mut *self.value }
1336    }
1337}
1338
1339/// An owned, reference-counted guard that releases the write lock when dropped.
1340#[clippy::has_significant_drop]
1341pub struct RwLockWriteGuardArc<T: ?Sized> {
1342    lock: Arc<RwLock<T>>,
1343}
1344
1345unsafe impl<T: Send + Sync + ?Sized> Send for RwLockWriteGuardArc<T> {}
1346unsafe impl<T: Send + Sync + ?Sized> Sync for RwLockWriteGuardArc<T> {}
1347
1348impl<T: ?Sized> Drop for RwLockWriteGuardArc<T> {
1349    #[inline]
1350    fn drop(&mut self) {
1351        // SAFETY: we are dropping a write lock.
1352        unsafe {
1353            self.lock.raw.write_unlock();
1354        }
1355    }
1356}
1357
1358impl<T> RwLockWriteGuardArc<T> {
1359    /// Downgrades into a regular reader guard.
1360    ///
1361    /// # Examples
1362    ///
1363    /// ```
1364    /// # futures_lite::future::block_on(async {
1365    /// use std::sync::Arc;
1366    /// use async_lock::{RwLock, RwLockWriteGuardArc};
1367    ///
1368    /// let lock = Arc::new(RwLock::new(1));
1369    ///
1370    /// let mut writer = lock.write_arc().await;
1371    /// *writer += 1;
1372    ///
1373    /// assert!(lock.try_read_arc().is_none());
1374    ///
1375    /// let reader = RwLockWriteGuardArc::downgrade(writer);
1376    /// assert_eq!(*reader, 2);
1377    ///
1378    /// assert!(lock.try_read_arc().is_some());
1379    /// # })
1380    /// ```
1381    #[inline]
1382    pub fn downgrade(guard: Self) -> RwLockReadGuardArc<T> {
1383        // SAFETY: `write` is a write guard
1384        unsafe {
1385            guard.lock.raw.downgrade_write();
1386        }
1387
1388        // SAFETY: we just downgraded to a read lock
1389        unsafe { RwLockReadGuardArc::from_arc(Self::into_arc(guard)) }
1390    }
1391}
1392
1393impl<T: ?Sized> RwLockWriteGuardArc<T> {
1394    /// Consumes the lock (without dropping) and returns the underlying `Arc`.
1395    #[inline]
1396    fn into_arc(guard: Self) -> Arc<RwLock<T>> {
1397        let guard = ManuallyDrop::new(guard);
1398        // SAFETY: `guard` is not used after this
1399        unsafe { ptr::read(&guard.lock) }
1400    }
1401
1402    /// Downgrades into an upgradable reader guard.
1403    ///
1404    /// # Examples
1405    ///
1406    /// ```
1407    /// # futures_lite::future::block_on(async {
1408    /// use std::sync::Arc;
1409    /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc, RwLockWriteGuardArc};
1410    ///
1411    /// let lock = Arc::new(RwLock::new(1));
1412    ///
1413    /// let mut writer = lock.write_arc().await;
1414    /// *writer += 1;
1415    ///
1416    /// assert!(lock.try_read_arc().is_none());
1417    ///
1418    /// let reader = RwLockWriteGuardArc::downgrade_to_upgradable(writer);
1419    /// assert_eq!(*reader, 2);
1420    ///
1421    /// assert!(lock.try_write_arc().is_none());
1422    /// assert!(lock.try_read_arc().is_some());
1423    ///
1424    /// assert!(RwLockUpgradableReadGuardArc::try_upgrade(reader).is_ok())
1425    /// # })
1426    /// ```
1427    #[inline]
1428    pub fn downgrade_to_upgradable(guard: Self) -> RwLockUpgradableReadGuardArc<T> {
1429        // SAFETY: `guard` is a write guard
1430        unsafe {
1431            guard.lock.raw.downgrade_to_upgradable();
1432        }
1433
1434        RwLockUpgradableReadGuardArc {
1435            lock: Self::into_arc(guard),
1436        }
1437    }
1438}
1439
1440impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockWriteGuardArc<T> {
1441    #[inline]
1442    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1443        fmt::Debug::fmt(&**self, f)
1444    }
1445}
1446
1447impl<T: fmt::Display + ?Sized> fmt::Display for RwLockWriteGuardArc<T> {
1448    #[inline]
1449    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1450        (**self).fmt(f)
1451    }
1452}
1453
1454impl<T: ?Sized> Deref for RwLockWriteGuardArc<T> {
1455    type Target = T;
1456
1457    #[inline]
1458    fn deref(&self) -> &T {
1459        unsafe { &*self.lock.value.get() }
1460    }
1461}
1462
1463impl<T: ?Sized> DerefMut for RwLockWriteGuardArc<T> {
1464    #[inline]
1465    fn deref_mut(&mut self) -> &mut T {
1466        unsafe { &mut *self.lock.value.get() }
1467    }
1468}