@@ -369,7 +369,7 @@ impl<T: ?Sized> RwLock<T> {
369
369
370
370
// If there are no readers, grab the write lock.
371
371
if self . state . compare_and_swap ( 0 , WRITER_BIT , Ordering :: AcqRel ) == 0 {
372
- Some ( RwLockWriteGuard ( self , lock) )
372
+ Some ( RwLockWriteGuard { writer : RwLockWriteGuardInner ( self ) , reserved : lock } )
373
373
} else {
374
374
None
375
375
}
@@ -397,7 +397,7 @@ impl<T: ?Sized> RwLock<T> {
397
397
398
398
// Set `WRITER_BIT` and create a guard that unsets it in case this future is canceled.
399
399
self . state . fetch_or ( WRITER_BIT , Ordering :: SeqCst ) ;
400
- let guard = RwLockWriteGuard ( self , lock) ;
400
+ let guard = RwLockWriteGuard { writer : RwLockWriteGuardInner ( self ) , reserved : lock } ;
401
401
402
402
// If there are readers, we need to wait for them to finish.
403
403
while self . state . load ( Ordering :: SeqCst ) != WRITER_BIT {
@@ -512,11 +512,36 @@ unsafe impl<T: Sync + ?Sized> Sync for RwLockUpgradableReadGuard<'_, T> {}
512
512
impl < ' a , T : ?Sized > RwLockUpgradableReadGuard < ' a , T > {
513
513
/// Converts this guard into a write guard.
514
514
fn into_writer ( self ) -> RwLockWriteGuard < ' a , T > {
515
- let writer = RwLockWriteGuard ( self . reader . 0 , self . reserved ) ;
515
+ let writer = RwLockWriteGuard { writer : RwLockWriteGuardInner ( self . reader . 0 ) , reserved : self . reserved } ;
516
516
mem:: forget ( self . reader ) ;
517
517
writer
518
518
}
519
519
520
+ /// Converts this guard into a reader guard.
521
+ ///
522
+ /// # Examples
523
+ ///
524
+ /// ```
525
+ /// # futures_lite::future::block_on(async {
526
+ /// use async_rwlock::{RwLock, RwLockUpgradableReadGuard};
527
+ ///
528
+ /// let lock = RwLock::new(1);
529
+ ///
530
+ /// let reader = lock.upgradable_read().await;
531
+ /// assert_eq!(*reader, 1);
532
+ ///
533
+ /// assert!(lock.try_upgradable_read().is_none());
534
+ ///
535
+ /// let reader = RwLockUpgradableReadGuard::downgrade(reader);
536
+ ///
537
+ /// assert!(lock.try_upgradable_read().is_some());
538
+ /// # })
539
+ /// ```
540
+ #[ inline]
541
+ pub fn downgrade ( guard : Self ) -> RwLockReadGuard < ' a , T > {
542
+ guard. reader
543
+ }
544
+
520
545
/// Attempts to upgrade into a write lock.
521
546
///
522
547
/// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise,
@@ -586,12 +611,12 @@ impl<'a, T: ?Sized> RwLockUpgradableReadGuard<'a, T> {
586
611
let guard = guard. into_writer ( ) ;
587
612
588
613
// If there are readers, we need to wait for them to finish.
589
- while guard. 0 . state . load ( Ordering :: SeqCst ) != WRITER_BIT {
614
+ while guard. writer . 0 . state . load ( Ordering :: SeqCst ) != WRITER_BIT {
590
615
// Start listening for "no readers" events.
591
- let listener = guard. 0 . no_readers . listen ( ) ;
616
+ let listener = guard. writer . 0 . no_readers . listen ( ) ;
592
617
593
618
// Check again if there are readers.
594
- if guard. 0 . state . load ( Ordering :: Acquire ) != WRITER_BIT {
619
+ if guard. writer . 0 . state . load ( Ordering :: Acquire ) != WRITER_BIT {
595
620
// Wait for the readers to finish.
596
621
listener. await ;
597
622
}
@@ -621,13 +646,9 @@ impl<T: ?Sized> Deref for RwLockUpgradableReadGuard<'_, T> {
621
646
}
622
647
}
623
648
624
- /// A guard that releases the write lock when dropped.
625
- pub struct RwLockWriteGuard < ' a , T : ?Sized > ( & ' a RwLock < T > , MutexGuard < ' a , ( ) > ) ;
626
-
627
- unsafe impl < T : Send + ?Sized > Send for RwLockWriteGuard < ' _ , T > { }
628
- unsafe impl < T : Sync + ?Sized > Sync for RwLockWriteGuard < ' _ , T > { }
649
+ struct RwLockWriteGuardInner < ' a , T : ?Sized > ( & ' a RwLock < T > ) ;
629
650
630
- impl < T : ?Sized > Drop for RwLockWriteGuard < ' _ , T > {
651
+ impl < T : ?Sized > Drop for RwLockWriteGuardInner < ' _ , T > {
631
652
fn drop ( & mut self ) {
632
653
// Unset `WRITER_BIT`.
633
654
self . 0 . state . fetch_and ( !WRITER_BIT , Ordering :: SeqCst ) ;
@@ -636,6 +657,88 @@ impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
636
657
}
637
658
}
638
659
660
+ /// A guard that releases the write lock when dropped.
661
+ pub struct RwLockWriteGuard < ' a , T : ?Sized > {
662
+ writer : RwLockWriteGuardInner < ' a , T > ,
663
+ reserved : MutexGuard < ' a , ( ) > ,
664
+ }
665
+
666
+ unsafe impl < T : Send + ?Sized > Send for RwLockWriteGuard < ' _ , T > { }
667
+ unsafe impl < T : Sync + ?Sized > Sync for RwLockWriteGuard < ' _ , T > { }
668
+
669
+ impl < ' a , T : ?Sized > RwLockWriteGuard < ' a , T > {
670
+ /// Converts this guard into a reader guard.
671
+ ///
672
+ /// # Examples
673
+ ///
674
+ /// ```
675
+ /// # futures_lite::future::block_on(async {
676
+ /// use async_rwlock::{RwLock, RwLockWriteGuard};
677
+ ///
678
+ /// let lock = RwLock::new(1);
679
+ ///
680
+ /// let mut writer = lock.write().await;
681
+ /// *writer += 1;
682
+ ///
683
+ /// assert!(lock.try_read().is_none());
684
+ ///
685
+ /// let reader = RwLockWriteGuard::downgrade(writer);
686
+ /// assert_eq!(*reader, 2);
687
+ ///
688
+ /// assert!(lock.try_read().is_some());
689
+ /// # })
690
+ /// ```
691
+ #[ inline]
692
+ pub fn downgrade ( write_guard : Self ) -> RwLockReadGuard < ' a , T > {
693
+ // Atomically downgrade state.
694
+ write_guard. writer . 0 . state . fetch_add ( ONE_READER - WRITER_BIT , Ordering :: SeqCst ) ;
695
+ // Trigger the "no writer" event.
696
+ write_guard. writer . 0 . no_writer . notify ( 1 ) ;
697
+ // Create and return the read guard
698
+ let read_guard = RwLockReadGuard ( write_guard. writer . 0 ) ;
699
+ mem:: forget ( write_guard. writer ) ; // RwLockWriteGuardInner::drop should not be called !
700
+ read_guard
701
+ }
702
+
703
+ /// Atomically downgrades a write lock into an upgradable read lock
704
+ /// without allowing any writers to take exclusive access of the lock in the meantime.
705
+ ///
706
+ /// # Examples
707
+ ///
708
+ /// ```
709
+ /// # futures_lite::future::block_on(async {
710
+ /// use async_rwlock::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard};
711
+ ///
712
+ /// let lock = RwLock::new(1);
713
+ ///
714
+ /// let mut writer = lock.write().await;
715
+ /// *writer += 1;
716
+ ///
717
+ /// assert!(lock.try_read().is_none());
718
+ ///
719
+ /// let reader = RwLockWriteGuard::downgrade_to_upgradable(writer);
720
+ /// assert_eq!(*reader, 2);
721
+ ///
722
+ /// assert!(lock.try_write().is_none());
723
+ /// assert!(lock.try_read().is_some());
724
+ ///
725
+ /// assert!(RwLockUpgradableReadGuard::try_upgrade(reader).is_ok())
726
+ /// # })
727
+ /// ```
728
+ pub fn downgrade_to_upgradable ( guard : Self ) -> RwLockUpgradableReadGuard < ' a , T > {
729
+ // Atomically downgrade state.
730
+ guard. writer . 0 . state . fetch_add ( ONE_READER - WRITER_BIT , Ordering :: SeqCst ) ;
731
+ // Create and return the upgradable read guard
732
+ let reader = RwLockReadGuard ( guard. writer . 0 ) ;
733
+ mem:: forget ( guard. writer ) ; // RwLockWriteGuardInner::drop should not be called !
734
+
735
+ RwLockUpgradableReadGuard {
736
+ reader,
737
+ reserved : guard. reserved ,
738
+ }
739
+ }
740
+ }
741
+
639
742
impl < T : fmt:: Debug + ?Sized > fmt:: Debug for RwLockWriteGuard < ' _ , T > {
640
743
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
641
744
fmt:: Debug :: fmt ( & * * self , f)
@@ -652,12 +755,12 @@ impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
652
755
type Target = T ;
653
756
654
757
fn deref ( & self ) -> & T {
655
- unsafe { & * self . 0 . value . get ( ) }
758
+ unsafe { & * self . writer . 0 . value . get ( ) }
656
759
}
657
760
}
658
761
659
762
impl < T : ?Sized > DerefMut for RwLockWriteGuard < ' _ , T > {
660
763
fn deref_mut ( & mut self ) -> & mut T {
661
- unsafe { & mut * self . 0 . value . get ( ) }
764
+ unsafe { & mut * self . writer . 0 . value . get ( ) }
662
765
}
663
766
}
0 commit comments