@@ -650,7 +650,7 @@ mod private {
650650 serde:: Raw ,
651651 } ;
652652 use tokio:: sync:: {
653- RwLock , RwLockReadGuard , RwLockWriteGuard , Semaphore ,
653+ Mutex , RwLock , RwLockReadGuard , RwLockWriteGuard ,
654654 broadcast:: { Receiver , Sender } ,
655655 } ;
656656 use tracing:: { debug, error, instrument, trace, warn} ;
@@ -678,7 +678,7 @@ mod private {
678678
679679 /// Please see inline comment of [`Self::read`] to understand why it
680680 /// exists.
681- read_lock_acquisition : Semaphore ,
681+ read_lock_acquisition : Mutex < ( ) > ,
682682 }
683683
684684 struct RoomEventCacheStateLockInner {
@@ -838,7 +838,7 @@ mod private {
838838 waited_for_initial_prev_token,
839839 subscriber_count : Default :: default ( ) ,
840840 } ) ,
841- read_lock_acquisition : Semaphore :: new ( 1 ) ,
841+ read_lock_acquisition : Mutex :: new ( ( ) ) ,
842842 } )
843843 }
844844
@@ -860,10 +860,10 @@ mod private {
860860 // ## Upgradable read lock
861861 //
862862 // One may argue that this upgrades can be done with an _upgradable read lock_
863- // [^1] [^2]. We don't want to use this solution because an upgradable read lock
864- // is basically a mutex because we are losing the shared access property: having
865- // multiple read locks at the same time. This is an important property to hold
866- // for performance concerns.
863+ // [^1] [^2]. We don't want to use this solution: an upgradable read lock is
864+ // basically a mutex because we are losing the shared access property, i.e.
865+ // having multiple read locks at the same time. This is an important property to
866+ // hold for performance concerns.
867867 //
868868 // ## Downgradable write lock
869869 //
@@ -886,30 +886,19 @@ mod private {
886886 // new lock acquisition, and it's not possible to pause the runtime in the
887887 // meantime.
888888 //
889- // ## Semaphore
889+ // ## Semaphore with 1 permit, aka a Mutex
890890 //
891- // The chosen idea is to allow only one execution at a time of this method. That
892- // way we are free to “upgrade” the read lock by dropping it and obtaining a new
893- // write lock. All callers to this method are waiting, so nothing can happen in
894- // the meantime.
891+ // The chosen idea is to allow only one execution at a time of this method: it
892+ // becomes a critical section. That way we are free to “upgrade” the read lock
893+ // by dropping it and obtaining a new write lock. All callers to this method are
894+ // waiting, so nothing can happen in the meantime.
895895 //
896896 // Note that it doesn't conflict with the `write` method because this later
897897 // immediately obtains a write lock, which avoids any conflict with this method.
898898 //
899899 // [^1]: https://docs.rs/lock_api/0.4.14/lock_api/struct.RwLock.html#method.upgradable_read
900900 // [^2]: https://docs.rs/async-lock/3.4.1/async_lock/struct.RwLock.html#method.upgradable_read
901- let _permit = self
902- . read_lock_acquisition
903- . acquire ( )
904- . await
905- . expect ( "The `lock_acquisition` semaphore must never be closed" ) ;
906-
907- // Just a check in case the code is modified without knowing how it works.
908- debug_assert_eq ! (
909- self . read_lock_acquisition. available_permits( ) ,
910- 0 ,
911- "The semaphore must have only one permit"
912- ) ;
901+ let _one_reader_guard = self . read_lock_acquisition . lock ( ) . await ;
913902
914903 // Obtain a read lock.
915904 let state_guard = self . locked_state . read ( ) . await ;
@@ -920,7 +909,8 @@ mod private {
920909 }
921910 EventCacheStoreLockState :: Dirty ( store_guard) => {
922911 // Drop the read lock, and take a write lock to modify the state.
923- // This is safe because only one semaphore permit exists.
912+ // This is safe because only one reader at a time (see
913+ // `Self::read_lock_acquisition`) is allowed.
924914 drop ( state_guard) ;
925915 let state_guard = self . locked_state . write ( ) . await ;
926916
0 commit comments