diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:19 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:19 +0000 |
commit | a0b8f38ab54ac451646aa00cd5e91b6c76f22a84 (patch) | |
tree | fc451898ccaf445814e26b46664d78702178101d /vendor/lock_api | |
parent | Adding debian version 1.71.1+dfsg1-2. (diff) | |
download | rustc-a0b8f38ab54ac451646aa00cd5e91b6c76f22a84.tar.xz rustc-a0b8f38ab54ac451646aa00cd5e91b6c76f22a84.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/lock_api')
-rw-r--r-- | vendor/lock_api/.cargo-checksum.json | 2 | ||||
-rw-r--r-- | vendor/lock_api/Cargo.toml | 11 | ||||
-rw-r--r-- | vendor/lock_api/src/lib.rs | 3 | ||||
-rw-r--r-- | vendor/lock_api/src/mutex.rs | 7 | ||||
-rw-r--r-- | vendor/lock_api/src/remutex.rs | 3 | ||||
-rw-r--r-- | vendor/lock_api/src/rwlock.rs | 263 |
6 files changed, 275 insertions, 14 deletions
diff --git a/vendor/lock_api/.cargo-checksum.json b/vendor/lock_api/.cargo-checksum.json index cf8df26fa..b4297e76f 100644 --- a/vendor/lock_api/.cargo-checksum.json +++ b/vendor/lock_api/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"15453a84e25ac6ed84c95e11e71d9bee5b360b6dc787a433b8416b91bf8e216c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"af84139c71d151adead0b4398c394a7dd16087bb2db44b14a0ed970ce868a6c6","src/lib.rs":"7b67c3b69c1b5e97248afe0f6c3bc353c793ed1ce4a5d5177e63f3f05d79c63b","src/mutex.rs":"f5627b1269a9b0d116507af19b8619b9922b95b73a84ab5be3134620c97caadb","src/remutex.rs":"4fa5f0448591a32ac37f2cf9af89813f32e415d2a1ca426670a0cdaccbca66aa","src/rwlock.rs":"9160cbada7e3179bd8ec13769761437e90bfb616316947dc0cc5959f0bcdc5b9"},"package":"435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"}
\ No newline at end of file +{"files":{"Cargo.toml":"12fd624e0a205bf395226b5ce7339f7d7060cd8be40c7603e517e0f0ff1ded84","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"af84139c71d151adead0b4398c394a7dd16087bb2db44b14a0ed970ce868a6c6","src/lib.rs":"4d2f97a740d3bda0cf2ba0ccbaa44a294952a701fc5a8219a755b4187bab29d4","src/mutex.rs":"eb6b92e848c3736fa463bec45eb7a8f2738cad2d4b36b3931ca30b1e70ab46c9","src/remutex.rs":"cf4d2fe406cd663155f39e6b85cb41e9e5c497f4e39c868a0d00675be5dc1115","src/rwlock.rs":"ce0ff32edc011ddfac22598acb12f6615ffa6d4609ed8d1b33e59caeb403c554"},"package":"c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"}
\ No newline at end of file diff --git a/vendor/lock_api/Cargo.toml b/vendor/lock_api/Cargo.toml index b1ff8c4db..7a3f3a8ad 100644 --- a/vendor/lock_api/Cargo.toml +++ b/vendor/lock_api/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2018" name = "lock_api" -version = "0.4.9" +version = "0.4.10" authors = ["Amanieu d'Antras <amanieu@gmail.com>"] description = "Wrappers to create fully-featured Mutex and RwLock types. Compatible with no_std." keywords = [ @@ -28,6 +28,13 @@ categories = [ license = "MIT OR Apache-2.0" repository = "https://github.com/Amanieu/parking_lot" +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + [dependencies.owning_ref] version = "0.4.1" optional = true @@ -46,4 +53,6 @@ version = "1.1.0" [features] arc_lock = [] +atomic_usize = [] +default = ["atomic_usize"] nightly = [] diff --git a/vendor/lock_api/src/lib.rs b/vendor/lock_api/src/lib.rs index cfa53bce4..3ea417a41 100644 --- a/vendor/lock_api/src/lib.rs +++ b/vendor/lock_api/src/lib.rs @@ -86,6 +86,7 @@ //! requires the `alloc` crate to be present. #![no_std] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs)] #![warn(rust_2018_idioms)] @@ -106,7 +107,9 @@ unsafe impl Sync for GuardNoSend {} mod mutex; pub use crate::mutex::*; +#[cfg(feature = "atomic_usize")] mod remutex; +#[cfg(feature = "atomic_usize")] pub use crate::remutex::*; mod rwlock; diff --git a/vendor/lock_api/src/mutex.rs b/vendor/lock_api/src/mutex.rs index c97e5430b..29533c9a5 100644 --- a/vendor/lock_api/src/mutex.rs +++ b/vendor/lock_api/src/mutex.rs @@ -257,7 +257,7 @@ impl<R: RawMutex, T: ?Sized> Mutex<R, T> { /// # Safety /// /// This method must only be called if the current thread logically owns a - /// `MutexGuard` but that guard has be discarded using `mem::forget`. + /// `MutexGuard` but that guard has been discarded using `mem::forget`. /// Behavior is undefined if a mutex is unlocked when not locked. #[inline] pub unsafe fn force_unlock(&self) { @@ -344,7 +344,7 @@ impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> { /// # Safety /// /// This method must only be called if the current thread logically owns a - /// `MutexGuard` but that guard has be discarded using `mem::forget`. + /// `MutexGuard` but that guard has been discarded using `mem::forget`. /// Behavior is undefined if a mutex is unlocked when not locked. #[inline] pub unsafe fn force_unlock_fair(&self) { @@ -485,6 +485,7 @@ where /// /// The data protected by the mutex can be accessed through this guard via its /// `Deref` and `DerefMut` implementations. +#[clippy::has_significant_drop] #[must_use = "if unused the Mutex will immediately unlock"] pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> { mutex: &'a Mutex<R, T>, @@ -678,6 +679,7 @@ unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<' /// This is similar to the `MutexGuard` struct, except instead of using a reference to unlock the `Mutex` it /// uses an `Arc<Mutex>`. This has several advantages, most notably that it has an `'static` lifetime. #[cfg(feature = "arc_lock")] +#[clippy::has_significant_drop] #[must_use = "if unused the Mutex will immediately unlock"] pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> { mutex: Arc<Mutex<R, T>>, @@ -813,6 +815,7 @@ impl<R: RawMutex, T: ?Sized> Drop for ArcMutexGuard<R, T> { /// former doesn't support temporarily unlocking and re-locking, since that /// could introduce soundness issues if the locked object is modified by another /// thread. +#[clippy::has_significant_drop] #[must_use = "if unused the Mutex will immediately unlock"] pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> { raw: &'a R, diff --git a/vendor/lock_api/src/remutex.rs b/vendor/lock_api/src/remutex.rs index 3e2010f2b..a2f818523 100644 --- a/vendor/lock_api/src/remutex.rs +++ b/vendor/lock_api/src/remutex.rs @@ -599,6 +599,7 @@ where /// /// The data protected by the mutex can be accessed through this guard via its /// `Deref` implementation. +#[clippy::has_significant_drop] #[must_use = "if unused the ReentrantMutex will immediately unlock"] pub struct ReentrantMutexGuard<'a, R: RawMutex, G: GetThreadId, T: ?Sized> { remutex: &'a ReentrantMutex<R, G, T>, @@ -794,6 +795,7 @@ unsafe impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> StableAdd /// `Mutex` it uses an `Arc<ReentrantMutex>`. This has several advantages, most notably that it has an `'static` /// lifetime. #[cfg(feature = "arc_lock")] +#[clippy::has_significant_drop] #[must_use = "if unused the ReentrantMutex will immediately unlock"] pub struct ArcReentrantMutexGuard<R: RawMutex, G: GetThreadId, T: ?Sized> { remutex: Arc<ReentrantMutex<R, G, T>>, @@ -897,6 +899,7 @@ impl<R: RawMutex, G: GetThreadId, T: ?Sized> Drop for ArcReentrantMutexGuard<R, /// former doesn't support temporarily unlocking and re-locking, since that /// could introduce soundness issues if the locked object is modified by another /// thread. +#[clippy::has_significant_drop] #[must_use = "if unused the ReentrantMutex will immediately unlock"] pub struct MappedReentrantMutexGuard<'a, R: RawMutex, G: GetThreadId, T: ?Sized> { raw: &'a RawReentrantMutex<R, G>, diff --git a/vendor/lock_api/src/rwlock.rs b/vendor/lock_api/src/rwlock.rs index c972fb6c6..cfec59e16 100644 --- a/vendor/lock_api/src/rwlock.rs +++ b/vendor/lock_api/src/rwlock.rs @@ -1182,12 +1182,15 @@ impl<R: RawRwLock, T: ?Sized + fmt::Debug> fmt::Debug for RwLock<R, T> { /// RAII structure used to release the shared read access of a lock when /// dropped. +#[clippy::has_significant_drop] #[must_use = "if unused the RwLock will immediately unlock"] pub struct RwLockReadGuard<'a, R: RawRwLock, T: ?Sized> { rwlock: &'a RwLock<R, T>, marker: PhantomData<(&'a T, R::GuardMarker)>, } +unsafe impl<R: RawRwLock + Sync, T: Sync + ?Sized> Sync for RwLockReadGuard<'_, R, T> {} + impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { /// Returns a reference to the original reader-writer lock object. pub fn rwlock(s: &Self) -> &'a RwLock<R, T> { @@ -1246,8 +1249,6 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { /// Temporarily unlocks the `RwLock` to execute the given function. /// - /// The `RwLock` is unlocked a fair unlock protocol. - /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the `RwLock`. #[inline] @@ -1359,6 +1360,7 @@ unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadG /// This is similar to the `RwLockReadGuard` struct, except instead of using a reference to unlock the `RwLock` /// it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` lifetime. #[cfg(feature = "arc_lock")] +#[clippy::has_significant_drop] #[must_use = "if unused the RwLock will immediately unlock"] pub struct ArcRwLockReadGuard<R: RawRwLock, T: ?Sized> { rwlock: Arc<RwLock<R, T>>, @@ -1470,12 +1472,15 @@ impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockReadGuard /// RAII structure used to release the exclusive write access of a lock when /// dropped. +#[clippy::has_significant_drop] #[must_use = "if unused the RwLock will immediately unlock"] pub struct RwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> { rwlock: &'a RwLock<R, T>, marker: PhantomData<(&'a mut T, R::GuardMarker)>, } +unsafe impl<R: RawRwLock + Sync, T: Sync + ?Sized> Sync for RwLockWriteGuard<'_, R, T> {} + impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { /// Returns a reference to the original reader-writer lock object. pub fn rwlock(s: &Self) -> &'a RwLock<R, T> { @@ -1693,6 +1698,7 @@ unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWrite /// This is similar to the `RwLockWriteGuard` struct, except instead of using a reference to unlock the `RwLock` /// it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` lifetime. #[cfg(feature = "arc_lock")] +#[clippy::has_significant_drop] #[must_use = "if unused the RwLock will immediately unlock"] pub struct ArcRwLockWriteGuard<R: RawRwLock, T: ?Sized> { rwlock: Arc<RwLock<R, T>>, @@ -1858,6 +1864,7 @@ impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockWriteGuar /// RAII structure used to release the upgradable read access of a lock when /// dropped. +#[clippy::has_significant_drop] #[must_use = "if unused the RwLock will immediately unlock"] pub struct RwLockUpgradableReadGuard<'a, R: RawRwLockUpgrade, T: ?Sized> { rwlock: &'a RwLock<R, T>, @@ -1892,7 +1899,7 @@ impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, f() } - /// Atomically upgrades an upgradable read lock lock into a exclusive write lock, + /// Atomically upgrades an upgradable read lock lock into an exclusive write lock, /// blocking the current thread until it can be acquired. pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, R, T> { // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. @@ -1907,7 +1914,7 @@ impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, } } - /// Tries to atomically upgrade an upgradable read lock into a exclusive write lock. + /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock. /// /// If the access could not be granted at this time, then the current guard is returned. pub fn try_upgrade(s: Self) -> Result<RwLockWriteGuard<'a, R, T>, Self> { @@ -2000,10 +2007,60 @@ impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockUpgradableRead marker: PhantomData, } } + + /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock, + /// blocking the current thread until it can be acquired. + /// + /// Then, calls the provided closure with an exclusive reference to the lock's data. + /// + /// Finally, atomically downgrades the lock back to an upgradable read lock. + /// The closure's return value is wrapped in `Some` and returned. + /// + /// This function only requires a mutable reference to the guard, unlike + /// `upgrade` which takes the guard by value. + pub fn with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Ret { + unsafe { + self.rwlock.raw.upgrade(); + } + + // Safety: We just upgraded the lock, so we have mutable access to the data. + // This will restore the state the lock was in at the start of the function. + defer!(unsafe { self.rwlock.raw.downgrade_upgradable() }); + + // Safety: We upgraded the lock, so we have mutable access to the data. + // When this function returns, whether by drop or panic, + // the drop guard will downgrade it back to an upgradeable lock. + f(unsafe { &mut *self.rwlock.data.get() }) + } + + /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock. + /// + /// If the access could not be granted at this time, then `None` is returned. + /// + /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, + /// and finally downgrades the lock back to an upgradable read lock. + /// The closure's return value is wrapped in `Some` and returned. + /// + /// This function only requires a mutable reference to the guard, unlike + /// `try_upgrade` which takes the guard by value. + pub fn try_with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Option<Ret> { + if unsafe { self.rwlock.raw.try_upgrade() } { + // Safety: We just upgraded the lock, so we have mutable access to the data. + // This will restore the state the lock was in at the start of the function. + defer!(unsafe { self.rwlock.raw.downgrade_upgradable() }); + + // Safety: We upgraded the lock, so we have mutable access to the data. + // When this function returns, whether by drop or panic, + // the drop guard will downgrade it back to an upgradeable lock. + Some(f(unsafe { &mut *self.rwlock.data.get() })) + } else { + None + } + } } impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> { - /// Tries to atomically upgrade an upgradable read lock into a exclusive + /// Tries to atomically upgrade an upgradable read lock into an exclusive /// write lock, until a timeout is reached. /// /// If the access could not be granted before the timeout expires, then @@ -2025,7 +2082,7 @@ impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuar } } - /// Tries to atomically upgrade an upgradable read lock into a exclusive + /// Tries to atomically upgrade an upgradable read lock into an exclusive /// write lock, until a timeout is reached. /// /// If the access could not be granted before the timeout expires, then @@ -2049,6 +2106,72 @@ impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuar } } +impl<'a, R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> + RwLockUpgradableReadGuard<'a, R, T> +{ + /// Tries to atomically upgrade an upgradable read lock into an exclusive + /// write lock, until a timeout is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. + /// + /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, + /// and finally downgrades the lock back to an upgradable read lock. + /// The closure's return value is wrapped in `Some` and returned. + /// + /// This function only requires a mutable reference to the guard, unlike + /// `try_upgrade_for` which takes the guard by value. + pub fn try_with_upgraded_for<Ret, F: FnOnce(&mut T) -> Ret>( + &mut self, + timeout: R::Duration, + f: F, + ) -> Option<Ret> { + if unsafe { self.rwlock.raw.try_upgrade_for(timeout) } { + // Safety: We just upgraded the lock, so we have mutable access to the data. + // This will restore the state the lock was in at the start of the function. + defer!(unsafe { self.rwlock.raw.downgrade_upgradable() }); + + // Safety: We upgraded the lock, so we have mutable access to the data. + // When this function returns, whether by drop or panic, + // the drop guard will downgrade it back to an upgradeable lock. + Some(f(unsafe { &mut *self.rwlock.data.get() })) + } else { + None + } + } + + /// Tries to atomically upgrade an upgradable read lock into an exclusive + /// write lock, until a timeout is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. + /// + /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, + /// and finally downgrades the lock back to an upgradable read lock. + /// The closure's return value is wrapped in `Some` and returned. + /// + /// This function only requires a mutable reference to the guard, unlike + /// `try_upgrade_until` which takes the guard by value. + pub fn try_with_upgraded_until<Ret, F: FnOnce(&mut T) -> Ret>( + &mut self, + timeout: R::Instant, + f: F, + ) -> Option<Ret> { + if unsafe { self.rwlock.raw.try_upgrade_until(timeout) } { + // Safety: We just upgraded the lock, so we have mutable access to the data. + // This will restore the state the lock was in at the start of the function. + defer!(unsafe { self.rwlock.raw.downgrade_upgradable() }); + + // Safety: We upgraded the lock, so we have mutable access to the data. + // When this function returns, whether by drop or panic, + // the drop guard will downgrade it back to an upgradeable lock. + Some(f(unsafe { &mut *self.rwlock.data.get() })) + } else { + None + } + } +} + impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Deref for RwLockUpgradableReadGuard<'a, R, T> { type Target = T; #[inline] @@ -2094,6 +2217,7 @@ unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress /// `RwLock` it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` /// lifetime. #[cfg(feature = "arc_lock")] +#[clippy::has_significant_drop] #[must_use = "if unused the RwLock will immediately unlock"] pub struct ArcRwLockUpgradableReadGuard<R: RawRwLockUpgrade, T: ?Sized> { rwlock: Arc<RwLock<R, T>>, @@ -2123,7 +2247,7 @@ impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { f() } - /// Atomically upgrades an upgradable read lock lock into a exclusive write lock, + /// Atomically upgrades an upgradable read lock lock into an exclusive write lock, /// blocking the current thread until it can be acquired. pub fn upgrade(s: Self) -> ArcRwLockWriteGuard<R, T> { // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock. @@ -2142,7 +2266,7 @@ impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { } } - /// Tries to atomically upgrade an upgradable read lock into a exclusive write lock. + /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock. /// /// If the access could not be granted at this time, then the current guard is returned. pub fn try_upgrade(s: Self) -> Result<ArcRwLockWriteGuard<R, T>, Self> { @@ -2231,11 +2355,61 @@ impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> marker: PhantomData, } } + + /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock, + /// blocking the current thread until it can be acquired. + /// + /// Then, calls the provided closure with an exclusive reference to the lock's data. + /// + /// Finally, atomically downgrades the lock back to an upgradable read lock. + /// The closure's return value is returned. + /// + /// This function only requires a mutable reference to the guard, unlike + /// `upgrade` which takes the guard by value. + pub fn with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Ret { + unsafe { + self.rwlock.raw.upgrade(); + } + + // Safety: We just upgraded the lock, so we have mutable access to the data. + // This will restore the state the lock was in at the start of the function. + defer!(unsafe { self.rwlock.raw.downgrade_upgradable() }); + + // Safety: We upgraded the lock, so we have mutable access to the data. + // When this function returns, whether by drop or panic, + // the drop guard will downgrade it back to an upgradeable lock. + f(unsafe { &mut *self.rwlock.data.get() }) + } + + /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock. + /// + /// If the access could not be granted at this time, then `None` is returned. + /// + /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, + /// and finally downgrades the lock back to an upgradable read lock. + /// The closure's return value is wrapped in `Some` and returned. + /// + /// This function only requires a mutable reference to the guard, unlike + /// `try_upgrade` which takes the guard by value. + pub fn try_with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Option<Ret> { + if unsafe { self.rwlock.raw.try_upgrade() } { + // Safety: We just upgraded the lock, so we have mutable access to the data. + // This will restore the state the lock was in at the start of the function. + defer!(unsafe { self.rwlock.raw.downgrade_upgradable() }); + + // Safety: We upgraded the lock, so we have mutable access to the data. + // When this function returns, whether by drop or panic, + // the drop guard will downgrade it back to an upgradeable lock. + Some(f(unsafe { &mut *self.rwlock.data.get() })) + } else { + None + } + } } #[cfg(feature = "arc_lock")] impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { - /// Tries to atomically upgrade an upgradable read lock into a exclusive + /// Tries to atomically upgrade an upgradable read lock into an exclusive /// write lock, until a timeout is reached. /// /// If the access could not be granted before the timeout expires, then @@ -2259,7 +2433,7 @@ impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { } } - /// Tries to atomically upgrade an upgradable read lock into a exclusive + /// Tries to atomically upgrade an upgradable read lock into an exclusive /// write lock, until a timeout is reached. /// /// If the access could not be granted before the timeout expires, then @@ -2286,6 +2460,73 @@ impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> { } #[cfg(feature = "arc_lock")] +impl<R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade, T: ?Sized> + ArcRwLockUpgradableReadGuard<R, T> +{ + /// Tries to atomically upgrade an upgradable read lock into an exclusive + /// write lock, until a timeout is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. + /// + /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, + /// and finally downgrades the lock back to an upgradable read lock. + /// The closure's return value is wrapped in `Some` and returned. + /// + /// This function only requires a mutable reference to the guard, unlike + /// `try_upgrade_for` which takes the guard by value. + pub fn try_with_upgraded_for<Ret, F: FnOnce(&mut T) -> Ret>( + &mut self, + timeout: R::Duration, + f: F, + ) -> Option<Ret> { + if unsafe { self.rwlock.raw.try_upgrade_for(timeout) } { + // Safety: We just upgraded the lock, so we have mutable access to the data. + // This will restore the state the lock was in at the start of the function. + defer!(unsafe { self.rwlock.raw.downgrade_upgradable() }); + + // Safety: We upgraded the lock, so we have mutable access to the data. + // When this function returns, whether by drop or panic, + // the drop guard will downgrade it back to an upgradeable lock. + Some(f(unsafe { &mut *self.rwlock.data.get() })) + } else { + None + } + } + + /// Tries to atomically upgrade an upgradable read lock into an exclusive + /// write lock, until a timeout is reached. + /// + /// If the access could not be granted before the timeout expires, then + /// `None` is returned. + /// + /// Otherwise, calls the provided closure with an exclusive reference to the lock's data, + /// and finally downgrades the lock back to an upgradable read lock. + /// The closure's return value is wrapped in `Some` and returned. + /// + /// This function only requires a mutable reference to the guard, unlike + /// `try_upgrade_until` which takes the guard by value. + pub fn try_with_upgraded_until<Ret, F: FnOnce(&mut T) -> Ret>( + &mut self, + timeout: R::Instant, + f: F, + ) -> Option<Ret> { + if unsafe { self.rwlock.raw.try_upgrade_until(timeout) } { + // Safety: We just upgraded the lock, so we have mutable access to the data. + // This will restore the state the lock was in at the start of the function. + defer!(unsafe { self.rwlock.raw.downgrade_upgradable() }); + + // Safety: We upgraded the lock, so we have mutable access to the data. + // When this function returns, whether by drop or panic, + // the drop guard will downgrade it back to an upgradeable lock. + Some(f(unsafe { &mut *self.rwlock.data.get() })) + } else { + None + } + } +} + +#[cfg(feature = "arc_lock")] impl<R: RawRwLockUpgrade, T: ?Sized> Deref for ArcRwLockUpgradableReadGuard<R, T> { type Target = T; #[inline] @@ -2330,6 +2571,7 @@ impl<R: RawRwLockUpgrade, T: fmt::Display + ?Sized> fmt::Display /// former doesn't support temporarily unlocking and re-locking, since that /// could introduce soundness issues if the locked object is modified by another /// thread. +#[clippy::has_significant_drop] #[must_use = "if unused the RwLock will immediately unlock"] pub struct MappedRwLockReadGuard<'a, R: RawRwLock, T: ?Sized> { raw: &'a R, @@ -2465,6 +2707,7 @@ unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress /// former doesn't support temporarily unlocking and re-locking, since that /// could introduce soundness issues if the locked object is modified by another /// thread. +#[clippy::has_significant_drop] #[must_use = "if unused the RwLock will immediately unlock"] pub struct MappedRwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> { raw: &'a R, |