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}