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