diff options
Diffstat (limited to 'vendor/lock_api/src/rwlock.rs')
-rw-r--r-- | vendor/lock_api/src/rwlock.rs | 263 |
1 files changed, 253 insertions, 10 deletions
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, |