summaryrefslogtreecommitdiff
path: root/src/rwlock.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/rwlock.rs')
-rw-r--r--src/rwlock.rs111
1 files changed, 71 insertions, 40 deletions
diff --git a/src/rwlock.rs b/src/rwlock.rs
index c404934..9bfa1da 100644
--- a/src/rwlock.rs
+++ b/src/rwlock.rs
@@ -84,6 +84,18 @@ pub unsafe trait RawRwLock {
}
!acquired_lock
}
+
+ /// Check if this `RwLock` is currently exclusively locked.
+ fn is_locked_exclusive(&self) -> bool {
+ let acquired_lock = self.try_lock_shared();
+ if acquired_lock {
+ // Safety: A shared lock was successfully acquired above.
+ unsafe {
+ self.unlock_shared();
+ }
+ }
+ !acquired_lock
+ }
}
/// Additional methods for RwLocks which support fair unlocking.
@@ -502,6 +514,12 @@ impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
self.raw.is_locked()
}
+ /// Check if this `RwLock` is currently exclusively locked.
+ #[inline]
+ pub fn is_locked_exclusive(&self) -> bool {
+ self.raw.is_locked_exclusive()
+ }
+
/// Forcibly unlocks a read lock.
///
/// This is useful when combined with `mem::forget` to hold a lock without
@@ -590,7 +608,7 @@ impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
}
/// Locks this `RwLock` with read access, through an `Arc`.
- ///
+ ///
/// This method is similar to the `read` method; however, it requires the `RwLock` to be inside of an `Arc`
/// and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
@@ -602,8 +620,8 @@ impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
}
/// Attempts to lock this `RwLock` with read access, through an `Arc`.
- ///
- /// This method is similar to the `try_read` method; however, it requires the `RwLock` to be inside of an
+ ///
+ /// This method is similar to the `try_read` method; however, it requires the `RwLock` to be inside of an
/// `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
#[inline]
@@ -617,7 +635,7 @@ impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
}
/// Locks this `RwLock` with write access, through an `Arc`.
- ///
+ ///
/// This method is similar to the `write` method; however, it requires the `RwLock` to be inside of an `Arc`
/// and the resulting write guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
@@ -629,8 +647,8 @@ impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
}
/// Attempts to lock this `RwLock` with writ access, through an `Arc`.
- ///
- /// This method is similar to the `try_write` method; however, it requires the `RwLock` to be inside of an
+ ///
+ /// This method is similar to the `try_write` method; however, it requires the `RwLock` to be inside of an
/// `Arc` and the resulting write guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
#[inline]
@@ -744,12 +762,15 @@ impl<R: RawRwLockTimed, T: ?Sized> RwLock<R, T> {
}
/// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
- ///
+ ///
/// This method is similar to the `try_read_for` method; however, it requires the `RwLock` to be inside of an
/// `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
#[inline]
- pub fn try_read_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcRwLockReadGuard<R, T>> {
+ pub fn try_read_arc_for(
+ self: &Arc<Self>,
+ timeout: R::Duration,
+ ) -> Option<ArcRwLockReadGuard<R, T>> {
if self.raw.try_lock_shared_for(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.read_guard_arc() })
@@ -759,12 +780,15 @@ impl<R: RawRwLockTimed, T: ?Sized> RwLock<R, T> {
}
/// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
- ///
+ ///
/// This method is similar to the `try_read_until` method; however, it requires the `RwLock` to be inside of
/// an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
#[inline]
- pub fn try_read_arc_until(self: &Arc<Self>, timeout: R::Instant) -> Option<ArcRwLockReadGuard<R, T>> {
+ pub fn try_read_arc_until(
+ self: &Arc<Self>,
+ timeout: R::Instant,
+ ) -> Option<ArcRwLockReadGuard<R, T>> {
if self.raw.try_lock_shared_until(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.read_guard_arc() })
@@ -774,12 +798,15 @@ impl<R: RawRwLockTimed, T: ?Sized> RwLock<R, T> {
}
/// Attempts to acquire this `RwLock` with write access until a timeout is reached, through an `Arc`.
- ///
+ ///
/// This method is similar to the `try_write_for` method; however, it requires the `RwLock` to be inside of
/// an `Arc` and the resulting write guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
#[inline]
- pub fn try_write_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcRwLockWriteGuard<R, T>> {
+ pub fn try_write_arc_for(
+ self: &Arc<Self>,
+ timeout: R::Duration,
+ ) -> Option<ArcRwLockWriteGuard<R, T>> {
if self.raw.try_lock_exclusive_for(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.write_guard_arc() })
@@ -789,12 +816,15 @@ impl<R: RawRwLockTimed, T: ?Sized> RwLock<R, T> {
}
/// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
- ///
+ ///
/// This method is similar to the `try_write_until` method; however, it requires the `RwLock` to be inside of
/// an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
#[inline]
- pub fn try_write_arc_until(self: &Arc<Self>, timeout: R::Instant) -> Option<ArcRwLockWriteGuard<R, T>> {
+ pub fn try_write_arc_until(
+ self: &Arc<Self>,
+ timeout: R::Instant,
+ ) -> Option<ArcRwLockWriteGuard<R, T>> {
if self.raw.try_lock_exclusive_until(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.write_guard_arc() })
@@ -848,7 +878,7 @@ impl<R: RawRwLockRecursive, T: ?Sized> RwLock<R, T> {
}
/// Locks this `RwLock` with shared read access, through an `Arc`.
- ///
+ ///
/// This method is similar to the `read_recursive` method; however, it requires the `RwLock` to be inside of
/// an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
@@ -860,7 +890,7 @@ impl<R: RawRwLockRecursive, T: ?Sized> RwLock<R, T> {
}
/// Attempts to lock this `RwLock` with shared read access, through an `Arc`.
- ///
+ ///
/// This method is similar to the `try_read_recursive` method; however, it requires the `RwLock` to be inside
/// of an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
@@ -924,7 +954,10 @@ impl<R: RawRwLockRecursiveTimed, T: ?Sized> RwLock<R, T> {
/// inside of an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
#[inline]
- pub fn try_read_arc_recursive_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcRwLockReadGuard<R, T>> {
+ pub fn try_read_arc_recursive_for(
+ self: &Arc<Self>,
+ timeout: R::Duration,
+ ) -> Option<ArcRwLockReadGuard<R, T>> {
if self.raw.try_lock_shared_recursive_for(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.read_guard_arc() })
@@ -939,7 +972,10 @@ impl<R: RawRwLockRecursiveTimed, T: ?Sized> RwLock<R, T> {
/// inside of an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
#[inline]
- pub fn try_read_arc_recursive_until(self: &Arc<Self>, timeout: R::Instant) -> Option<ArcRwLockReadGuard<R, T>> {
+ pub fn try_read_arc_recursive_until(
+ self: &Arc<Self>,
+ timeout: R::Instant,
+ ) -> Option<ArcRwLockReadGuard<R, T>> {
if self.raw.try_lock_shared_recursive_until(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.read_guard_arc() })
@@ -995,19 +1031,19 @@ impl<R: RawRwLockUpgrade, T: ?Sized> RwLock<R, T> {
}
/// # Safety
- ///
+ ///
/// The lock must be held when calling this method.
#[cfg(feature = "arc_lock")]
#[inline]
unsafe fn upgradable_guard_arc(self: &Arc<Self>) -> ArcRwLockUpgradableReadGuard<R, T> {
ArcRwLockUpgradableReadGuard {
rwlock: self.clone(),
- marker: PhantomData
+ marker: PhantomData,
}
}
/// Locks this `RwLock` with upgradable read access, through an `Arc`.
- ///
+ ///
/// This method is similar to the `upgradable_read` method; however, it requires the `RwLock` to be
/// inside of an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
@@ -1019,7 +1055,7 @@ impl<R: RawRwLockUpgrade, T: ?Sized> RwLock<R, T> {
}
/// Attempts to lock this `RwLock` with upgradable read access, through an `Arc`.
- ///
+ ///
/// This method is similar to the `try_upgradable_read` method; however, it requires the `RwLock` to be
/// inside of an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
@@ -1074,7 +1110,7 @@ impl<R: RawRwLockUpgradeTimed, T: ?Sized> RwLock<R, T> {
}
/// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`.
- ///
+ ///
/// This method is similar to the `try_upgradable_read_for` method; however, it requires the `RwLock` to be
/// inside of an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
@@ -1092,7 +1128,7 @@ impl<R: RawRwLockUpgradeTimed, T: ?Sized> RwLock<R, T> {
}
/// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`.
- ///
+ ///
/// This method is similar to the `try_upgradable_read_until` method; however, it requires the `RwLock` to be
/// inside of an `Arc` and the resulting read guard has no lifetime requirements.
#[cfg(feature = "arc_lock")]
@@ -1318,9 +1354,9 @@ impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadGuard<'a, R, T> {}
-/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
-///
-/// This is similar to the `RwLockReadGuard` struct, except instead of using a reference to unlock the `RwLock`
+/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
+///
+/// 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")]
#[must_use = "if unused the RwLock will immediately unlock"]
@@ -1426,9 +1462,7 @@ impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockReadGuard<R,
}
#[cfg(feature = "arc_lock")]
-impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display
- for ArcRwLockReadGuard<R, T>
-{
+impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockReadGuard<R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
@@ -1655,8 +1689,8 @@ impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWriteGuard<'a, R, T> {}
-/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
-/// This is similar to the `RwLockWriteGuard` struct, except instead of using a reference to unlock the `RwLock`
+/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
+/// 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")]
#[must_use = "if unused the RwLock will immediately unlock"]
@@ -1770,7 +1804,7 @@ impl<R: RawRwLockFair, T: ?Sized> ArcRwLockWriteGuard<R, T> {
/// Temporarily yields the `RwLock` to a waiting thread if there is one.
///
- /// This method is functionally equivalent to the `bump` method on [`RwLockWriteGuard`].
+ /// This method is functionally equivalent to the `bump` method on [`RwLockWriteGuard`].
#[inline]
pub fn bump(s: &mut Self) {
// Safety: An RwLockWriteGuard always holds an exclusive lock.
@@ -1816,9 +1850,7 @@ impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockWriteGuard<R,
}
#[cfg(feature = "arc_lock")]
-impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display
- for ArcRwLockWriteGuard<R, T>
-{
+impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockWriteGuard<R, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
@@ -2059,7 +2091,7 @@ unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress
/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
/// This is similar to the `RwLockUpgradableReadGuard` 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`
+/// `RwLock` it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static`
/// lifetime.
#[cfg(feature = "arc_lock")]
#[must_use = "if unused the RwLock will immediately unlock"]
@@ -2069,7 +2101,7 @@ pub struct ArcRwLockUpgradableReadGuard<R: RawRwLockUpgrade, T: ?Sized> {
}
#[cfg(feature = "arc_lock")]
-impl<R: RawRwLockUpgrade , T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
+impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
/// Returns a reference to the rwlock, contained in its original `Arc`.
pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
&s.rwlock
@@ -2144,7 +2176,7 @@ impl<R: RawRwLockUpgradeFair, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
// SAFETY: make sure we decrement the refcount properly
let mut s = ManuallyDrop::new(s);
- unsafe { ptr::drop_in_place(&mut s.rwlock) };
+ unsafe { ptr::drop_in_place(&mut s.rwlock) };
}
/// Temporarily unlocks the `RwLock` to execute the given function.
@@ -2291,7 +2323,6 @@ impl<R: RawRwLockUpgrade, T: fmt::Display + ?Sized> fmt::Display
}
}
-
/// An RAII read lock guard returned by `RwLockReadGuard::map`, which can point to a
/// subfield of the protected data.
///