@@ -369,7 +369,7 @@ impl<T: ?Sized> RwLock<T> {
369369
370370 // If there are no readers, grab the write lock.
371371 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 } )
373373 } else {
374374 None
375375 }
@@ -397,7 +397,7 @@ impl<T: ?Sized> RwLock<T> {
397397
398398 // Set `WRITER_BIT` and create a guard that unsets it in case this future is canceled.
399399 self . state . fetch_or ( WRITER_BIT , Ordering :: SeqCst ) ;
400- let guard = RwLockWriteGuard ( self , lock) ;
400+ let guard = RwLockWriteGuard { writer : RwLockWriteGuardInner ( self ) , reserved : lock } ;
401401
402402 // If there are readers, we need to wait for them to finish.
403403 while self . state . load ( Ordering :: SeqCst ) != WRITER_BIT {
@@ -512,11 +512,36 @@ unsafe impl<T: Sync + ?Sized> Sync for RwLockUpgradableReadGuard<'_, T> {}
512512impl < ' a , T : ?Sized > RwLockUpgradableReadGuard < ' a , T > {
513513 /// Converts this guard into a write guard.
514514 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 } ;
516516 mem:: forget ( self . reader ) ;
517517 writer
518518 }
519519
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+
520545 /// Attempts to upgrade into a write lock.
521546 ///
522547 /// 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> {
586611 let guard = guard. into_writer ( ) ;
587612
588613 // 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 {
590615 // Start listening for "no readers" events.
591- let listener = guard. 0 . no_readers . listen ( ) ;
616+ let listener = guard. writer . 0 . no_readers . listen ( ) ;
592617
593618 // 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 {
595620 // Wait for the readers to finish.
596621 listener. await ;
597622 }
@@ -621,13 +646,9 @@ impl<T: ?Sized> Deref for RwLockUpgradableReadGuard<'_, T> {
621646 }
622647}
623648
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 > ) ;
629650
630- impl < T : ?Sized > Drop for RwLockWriteGuard < ' _ , T > {
651+ impl < T : ?Sized > Drop for RwLockWriteGuardInner < ' _ , T > {
631652 fn drop ( & mut self ) {
632653 // Unset `WRITER_BIT`.
633654 self . 0 . state . fetch_and ( !WRITER_BIT , Ordering :: SeqCst ) ;
@@ -636,6 +657,88 @@ impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
636657 }
637658}
638659
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+
639742impl < T : fmt:: Debug + ?Sized > fmt:: Debug for RwLockWriteGuard < ' _ , T > {
640743 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
641744 fmt:: Debug :: fmt ( & * * self , f)
@@ -652,12 +755,12 @@ impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
652755 type Target = T ;
653756
654757 fn deref ( & self ) -> & T {
655- unsafe { & * self . 0 . value . get ( ) }
758+ unsafe { & * self . writer . 0 . value . get ( ) }
656759 }
657760}
658761
659762impl < T : ?Sized > DerefMut for RwLockWriteGuard < ' _ , T > {
660763 fn deref_mut ( & mut self ) -> & mut T {
661- unsafe { & mut * self . 0 . value . get ( ) }
764+ unsafe { & mut * self . writer . 0 . value . get ( ) }
662765 }
663766}
0 commit comments