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