summaryrefslogtreecommitdiffstats
path: root/vendor/lock_api
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:19 +0000
commita0b8f38ab54ac451646aa00cd5e91b6c76f22a84 (patch)
treefc451898ccaf445814e26b46664d78702178101d /vendor/lock_api
parentAdding debian version 1.71.1+dfsg1-2. (diff)
downloadrustc-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.json2
-rw-r--r--vendor/lock_api/Cargo.toml11
-rw-r--r--vendor/lock_api/src/lib.rs3
-rw-r--r--vendor/lock_api/src/mutex.rs7
-rw-r--r--vendor/lock_api/src/remutex.rs3
-rw-r--r--vendor/lock_api/src/rwlock.rs263
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,