@@ -1897,7 +1897,7 @@ impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a,
18971897 f ( )
18981898 }
18991899
1900- /// Atomically upgrades an upgradable read lock lock into a exclusive write lock,
1900+ /// Atomically upgrades an upgradable read lock lock into an exclusive write lock,
19011901 /// blocking the current thread until it can be acquired.
19021902 pub fn upgrade ( s : Self ) -> RwLockWriteGuard < ' a , R , T > {
19031903 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
@@ -1912,7 +1912,7 @@ impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a,
19121912 }
19131913 }
19141914
1915- /// Tries to atomically upgrade an upgradable read lock into a exclusive write lock.
1915+ /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock.
19161916 ///
19171917 /// If the access could not be granted at this time, then the current guard is returned.
19181918 pub fn try_upgrade ( s : Self ) -> Result < RwLockWriteGuard < ' a , R , T > , Self > {
@@ -2005,10 +2005,60 @@ impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockUpgradableRead
20052005 marker : PhantomData ,
20062006 }
20072007 }
2008+
2009+ /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock,
2010+ /// blocking the current thread until it can be acquired.
2011+ ///
2012+ /// Then, calls the provided closure with an exclusive reference to the lock's data.
2013+ ///
2014+ /// Finally, atomically downgrades the lock back to an upgradable read lock.
2015+ /// The closure's return value is wrapped in `Some` and returned.
2016+ ///
2017+ /// This function only requires a mutable reference to the guard, unlike
2018+ /// `upgrade` which takes the guard by value.
2019+ pub fn with_upgraded < Ret , F : FnOnce ( & mut T ) -> Ret > ( & mut self , f : F ) -> Ret {
2020+ unsafe {
2021+ self . rwlock . raw . upgrade ( ) ;
2022+ }
2023+
2024+ // Safety: We just upgraded the lock, so we have mutable access to the data.
2025+ // This will restore the state the lock was in at the start of the function.
2026+ defer ! ( unsafe { self . rwlock. raw. downgrade_upgradable( ) } ) ;
2027+
2028+ // Safety: We upgraded the lock, so we have mutable access to the data.
2029+ // When this function returns, whether by drop or panic,
2030+ // the drop guard will downgrade it back to an upgradeable lock.
2031+ f ( unsafe { & mut * self . rwlock . data . get ( ) } )
2032+ }
2033+
2034+ /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2035+ ///
2036+ /// If the access could not be granted at this time, then `None` is returned.
2037+ ///
2038+ /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2039+ /// and finally downgrades the lock back to an upgradable read lock.
2040+ /// The closure's return value is wrapped in `Some` and returned.
2041+ ///
2042+ /// This function only requires a mutable reference to the guard, unlike
2043+ /// `try_upgrade` which takes the guard by value.
2044+ pub fn try_with_upgraded < Ret , F : FnOnce ( & mut T ) -> Ret > ( & mut self , f : F ) -> Option < Ret > {
2045+ if unsafe { self . rwlock . raw . try_upgrade ( ) } {
2046+ // Safety: We just upgraded the lock, so we have mutable access to the data.
2047+ // This will restore the state the lock was in at the start of the function.
2048+ defer ! ( unsafe { self . rwlock. raw. downgrade_upgradable( ) } ) ;
2049+
2050+ // Safety: We upgraded the lock, so we have mutable access to the data.
2051+ // When this function returns, whether by drop or panic,
2052+ // the drop guard will downgrade it back to an upgradeable lock.
2053+ Some ( f ( unsafe { & mut * self . rwlock . data . get ( ) } ) )
2054+ } else {
2055+ None
2056+ }
2057+ }
20082058}
20092059
20102060impl < ' a , R : RawRwLockUpgradeTimed + ' a , T : ?Sized + ' a > RwLockUpgradableReadGuard < ' a , R , T > {
2011- /// Tries to atomically upgrade an upgradable read lock into a exclusive
2061+ /// Tries to atomically upgrade an upgradable read lock into an exclusive
20122062 /// write lock, until a timeout is reached.
20132063 ///
20142064 /// If the access could not be granted before the timeout expires, then
@@ -2030,7 +2080,7 @@ impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuar
20302080 }
20312081 }
20322082
2033- /// Tries to atomically upgrade an upgradable read lock into a exclusive
2083+ /// Tries to atomically upgrade an upgradable read lock into an exclusive
20342084 /// write lock, until a timeout is reached.
20352085 ///
20362086 /// If the access could not be granted before the timeout expires, then
@@ -2054,6 +2104,72 @@ impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuar
20542104 }
20552105}
20562106
2107+ impl < ' a , R : RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade + ' a , T : ?Sized + ' a >
2108+ RwLockUpgradableReadGuard < ' a , R , T >
2109+ {
2110+ /// Tries to atomically upgrade an upgradable read lock into an exclusive
2111+ /// write lock, until a timeout is reached.
2112+ ///
2113+ /// If the access could not be granted before the timeout expires, then
2114+ /// `None` is returned.
2115+ ///
2116+ /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2117+ /// and finally downgrades the lock back to an upgradable read lock.
2118+ /// The closure's return value is wrapped in `Some` and returned.
2119+ ///
2120+ /// This function only requires a mutable reference to the guard, unlike
2121+ /// `try_upgrade_for` which takes the guard by value.
2122+ pub fn try_with_upgraded_for < Ret , F : FnOnce ( & mut T ) -> Ret > (
2123+ & mut self ,
2124+ timeout : R :: Duration ,
2125+ f : F ,
2126+ ) -> Option < Ret > {
2127+ if unsafe { self . rwlock . raw . try_upgrade_for ( timeout) } {
2128+ // Safety: We just upgraded the lock, so we have mutable access to the data.
2129+ // This will restore the state the lock was in at the start of the function.
2130+ defer ! ( unsafe { self . rwlock. raw. downgrade_upgradable( ) } ) ;
2131+
2132+ // Safety: We upgraded the lock, so we have mutable access to the data.
2133+ // When this function returns, whether by drop or panic,
2134+ // the drop guard will downgrade it back to an upgradeable lock.
2135+ Some ( f ( unsafe { & mut * self . rwlock . data . get ( ) } ) )
2136+ } else {
2137+ None
2138+ }
2139+ }
2140+
2141+ /// Tries to atomically upgrade an upgradable read lock into an exclusive
2142+ /// write lock, until a timeout is reached.
2143+ ///
2144+ /// If the access could not be granted before the timeout expires, then
2145+ /// `None` is returned.
2146+ ///
2147+ /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2148+ /// and finally downgrades the lock back to an upgradable read lock.
2149+ /// The closure's return value is wrapped in `Some` and returned.
2150+ ///
2151+ /// This function only requires a mutable reference to the guard, unlike
2152+ /// `try_upgrade_until` which takes the guard by value.
2153+ pub fn try_with_upgraded_until < Ret , F : FnOnce ( & mut T ) -> Ret > (
2154+ & mut self ,
2155+ timeout : R :: Instant ,
2156+ f : F ,
2157+ ) -> Option < Ret > {
2158+ if unsafe { self . rwlock . raw . try_upgrade_until ( timeout) } {
2159+ // Safety: We just upgraded the lock, so we have mutable access to the data.
2160+ // This will restore the state the lock was in at the start of the function.
2161+ defer ! ( unsafe { self . rwlock. raw. downgrade_upgradable( ) } ) ;
2162+
2163+ // Safety: We upgraded the lock, so we have mutable access to the data.
2164+ // When this function returns, whether by drop or panic,
2165+ // the drop guard will downgrade it back to an upgradeable lock.
2166+ Some ( f ( unsafe { & mut * self . rwlock . data . get ( ) } ) )
2167+ } else {
2168+ None
2169+ }
2170+ }
2171+ }
2172+
20572173impl < ' a , R : RawRwLockUpgrade + ' a , T : ?Sized + ' a > Deref for RwLockUpgradableReadGuard < ' a , R , T > {
20582174 type Target = T ;
20592175 #[ inline]
@@ -2129,7 +2245,7 @@ impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
21292245 f ( )
21302246 }
21312247
2132- /// Atomically upgrades an upgradable read lock lock into a exclusive write lock,
2248+ /// Atomically upgrades an upgradable read lock lock into an exclusive write lock,
21332249 /// blocking the current thread until it can be acquired.
21342250 pub fn upgrade ( s : Self ) -> ArcRwLockWriteGuard < R , T > {
21352251 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
@@ -2148,7 +2264,7 @@ impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
21482264 }
21492265 }
21502266
2151- /// Tries to atomically upgrade an upgradable read lock into a exclusive write lock.
2267+ /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock.
21522268 ///
21532269 /// If the access could not be granted at this time, then the current guard is returned.
21542270 pub fn try_upgrade ( s : Self ) -> Result < ArcRwLockWriteGuard < R , T > , Self > {
@@ -2237,11 +2353,61 @@ impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T>
22372353 marker : PhantomData ,
22382354 }
22392355 }
2356+
2357+ /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock,
2358+ /// blocking the current thread until it can be acquired.
2359+ ///
2360+ /// Then, calls the provided closure with an exclusive reference to the lock's data.
2361+ ///
2362+ /// Finally, atomically downgrades the lock back to an upgradable read lock.
2363+ /// The closure's return value is returned.
2364+ ///
2365+ /// This function only requires a mutable reference to the guard, unlike
2366+ /// `upgrade` which takes the guard by value.
2367+ pub fn with_upgraded < Ret , F : FnOnce ( & mut T ) -> Ret > ( & mut self , f : F ) -> Ret {
2368+ unsafe {
2369+ self . rwlock . raw . upgrade ( ) ;
2370+ }
2371+
2372+ // Safety: We just upgraded the lock, so we have mutable access to the data.
2373+ // This will restore the state the lock was in at the start of the function.
2374+ defer ! ( unsafe { self . rwlock. raw. downgrade_upgradable( ) } ) ;
2375+
2376+ // Safety: We upgraded the lock, so we have mutable access to the data.
2377+ // When this function returns, whether by drop or panic,
2378+ // the drop guard will downgrade it back to an upgradeable lock.
2379+ f ( unsafe { & mut * self . rwlock . data . get ( ) } )
2380+ }
2381+
2382+ /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2383+ ///
2384+ /// If the access could not be granted at this time, then `None` is returned.
2385+ ///
2386+ /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2387+ /// and finally downgrades the lock back to an upgradable read lock.
2388+ /// The closure's return value is wrapped in `Some` and returned.
2389+ ///
2390+ /// This function only requires a mutable reference to the guard, unlike
2391+ /// `try_upgrade` which takes the guard by value.
2392+ pub fn try_with_upgraded < Ret , F : FnOnce ( & mut T ) -> Ret > ( & mut self , f : F ) -> Option < Ret > {
2393+ if unsafe { self . rwlock . raw . try_upgrade ( ) } {
2394+ // Safety: We just upgraded the lock, so we have mutable access to the data.
2395+ // This will restore the state the lock was in at the start of the function.
2396+ defer ! ( unsafe { self . rwlock. raw. downgrade_upgradable( ) } ) ;
2397+
2398+ // Safety: We upgraded the lock, so we have mutable access to the data.
2399+ // When this function returns, whether by drop or panic,
2400+ // the drop guard will downgrade it back to an upgradeable lock.
2401+ Some ( f ( unsafe { & mut * self . rwlock . data . get ( ) } ) )
2402+ } else {
2403+ None
2404+ }
2405+ }
22402406}
22412407
22422408#[ cfg( feature = "arc_lock" ) ]
22432409impl < R : RawRwLockUpgradeTimed , T : ?Sized > ArcRwLockUpgradableReadGuard < R , T > {
2244- /// Tries to atomically upgrade an upgradable read lock into a exclusive
2410+ /// Tries to atomically upgrade an upgradable read lock into an exclusive
22452411 /// write lock, until a timeout is reached.
22462412 ///
22472413 /// If the access could not be granted before the timeout expires, then
@@ -2265,7 +2431,7 @@ impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
22652431 }
22662432 }
22672433
2268- /// Tries to atomically upgrade an upgradable read lock into a exclusive
2434+ /// Tries to atomically upgrade an upgradable read lock into an exclusive
22692435 /// write lock, until a timeout is reached.
22702436 ///
22712437 /// If the access could not be granted before the timeout expires, then
@@ -2291,6 +2457,73 @@ impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
22912457 }
22922458}
22932459
2460+ #[ cfg( feature = "arc_lock" ) ]
2461+ impl < R : RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade , T : ?Sized >
2462+ ArcRwLockUpgradableReadGuard < R , T >
2463+ {
2464+ /// Tries to atomically upgrade an upgradable read lock into an exclusive
2465+ /// write lock, until a timeout is reached.
2466+ ///
2467+ /// If the access could not be granted before the timeout expires, then
2468+ /// `None` is returned.
2469+ ///
2470+ /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2471+ /// and finally downgrades the lock back to an upgradable read lock.
2472+ /// The closure's return value is wrapped in `Some` and returned.
2473+ ///
2474+ /// This function only requires a mutable reference to the guard, unlike
2475+ /// `try_upgrade_for` which takes the guard by value.
2476+ pub fn try_with_upgraded_for < Ret , F : FnOnce ( & mut T ) -> Ret > (
2477+ & mut self ,
2478+ timeout : R :: Duration ,
2479+ f : F ,
2480+ ) -> Option < Ret > {
2481+ if unsafe { self . rwlock . raw . try_upgrade_for ( timeout) } {
2482+ // Safety: We just upgraded the lock, so we have mutable access to the data.
2483+ // This will restore the state the lock was in at the start of the function.
2484+ defer ! ( unsafe { self . rwlock. raw. downgrade_upgradable( ) } ) ;
2485+
2486+ // Safety: We upgraded the lock, so we have mutable access to the data.
2487+ // When this function returns, whether by drop or panic,
2488+ // the drop guard will downgrade it back to an upgradeable lock.
2489+ Some ( f ( unsafe { & mut * self . rwlock . data . get ( ) } ) )
2490+ } else {
2491+ None
2492+ }
2493+ }
2494+
2495+ /// Tries to atomically upgrade an upgradable read lock into an exclusive
2496+ /// write lock, until a timeout is reached.
2497+ ///
2498+ /// If the access could not be granted before the timeout expires, then
2499+ /// `None` is returned.
2500+ ///
2501+ /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2502+ /// and finally downgrades the lock back to an upgradable read lock.
2503+ /// The closure's return value is wrapped in `Some` and returned.
2504+ ///
2505+ /// This function only requires a mutable reference to the guard, unlike
2506+ /// `try_upgrade_until` which takes the guard by value.
2507+ pub fn try_with_upgraded_until < Ret , F : FnOnce ( & mut T ) -> Ret > (
2508+ & mut self ,
2509+ timeout : R :: Instant ,
2510+ f : F ,
2511+ ) -> Option < Ret > {
2512+ if unsafe { self . rwlock . raw . try_upgrade_until ( timeout) } {
2513+ // Safety: We just upgraded the lock, so we have mutable access to the data.
2514+ // This will restore the state the lock was in at the start of the function.
2515+ defer ! ( unsafe { self . rwlock. raw. downgrade_upgradable( ) } ) ;
2516+
2517+ // Safety: We upgraded the lock, so we have mutable access to the data.
2518+ // When this function returns, whether by drop or panic,
2519+ // the drop guard will downgrade it back to an upgradeable lock.
2520+ Some ( f ( unsafe { & mut * self . rwlock . data . get ( ) } ) )
2521+ } else {
2522+ None
2523+ }
2524+ }
2525+ }
2526+
22942527#[ cfg( feature = "arc_lock" ) ]
22952528impl < R : RawRwLockUpgrade , T : ?Sized > Deref for ArcRwLockUpgradableReadGuard < R , T > {
22962529 type Target = T ;
0 commit comments