[core] Refactor lock::ranked to use LockStateGuard.

Rather than implementing `Drop` for all three lock guard types to
restore the lock analysis' per-thread state, let lock guards own
values of a new type, `LockStateGuard`, with the appropriate `Drop`
implementation. This is cleaner and shorter, and helps us implement
`RwLock::downgrade` in a later commit.
This commit is contained in:
Jim Blandy 2024-05-01 17:35:26 -07:00 committed by Erich Gubler
parent fb3b33d092
commit 651214ef74

View File

@ -81,7 +81,7 @@ pub struct Mutex<T> {
/// [mod]: crate::lock::ranked /// [mod]: crate::lock::ranked
pub struct MutexGuard<'a, T> { pub struct MutexGuard<'a, T> {
inner: parking_lot::MutexGuard<'a, T>, inner: parking_lot::MutexGuard<'a, T>,
saved: LockState, saved: LockStateGuard,
} }
thread_local! { thread_local! {
@ -107,6 +107,26 @@ impl LockState {
}; };
} }
/// A container that restores a [`LockState`] when dropped.
///
/// This type serves two purposes:
///
/// - Operations like `RwLockWriteGuard::downgrade` would like to be able to
/// destructure lock guards and reassemble their pieces into new guards, but
/// if the guard type itself implements `Drop`, we can't destructure it
/// without unsafe code or pointless `Option`s whose state is almost always
/// statically known.
///
/// - We can just implement `Drop` for this type once, and then use it in lock
/// guards, rather than implementing `Drop` separately for each guard type.
struct LockStateGuard(LockState);
impl Drop for LockStateGuard {
fn drop(&mut self) {
release(self.0)
}
}
/// Check and record the acquisition of a lock with `new_rank`. /// Check and record the acquisition of a lock with `new_rank`.
/// ///
/// Check that acquiring a lock with `new_rank` is permitted at this point, and /// Check that acquiring a lock with `new_rank` is permitted at this point, and
@ -170,17 +190,11 @@ impl<T> Mutex<T> {
let saved = acquire(self.rank, Location::caller()); let saved = acquire(self.rank, Location::caller());
MutexGuard { MutexGuard {
inner: self.inner.lock(), inner: self.inner.lock(),
saved, saved: LockStateGuard(saved),
} }
} }
} }
impl<'a, T> Drop for MutexGuard<'a, T> {
fn drop(&mut self) {
release(self.saved);
}
}
impl<'a, T> std::ops::Deref for MutexGuard<'a, T> { impl<'a, T> std::ops::Deref for MutexGuard<'a, T> {
type Target = T; type Target = T;
@ -224,7 +238,7 @@ pub struct RwLock<T> {
/// [mod]: crate::lock::ranked /// [mod]: crate::lock::ranked
pub struct RwLockReadGuard<'a, T> { pub struct RwLockReadGuard<'a, T> {
inner: parking_lot::RwLockReadGuard<'a, T>, inner: parking_lot::RwLockReadGuard<'a, T>,
saved: LockState, saved: LockStateGuard,
} }
/// A write guard produced by locking [`RwLock`] for writing. /// A write guard produced by locking [`RwLock`] for writing.
@ -237,7 +251,7 @@ pub struct RwLockReadGuard<'a, T> {
/// [mod]: crate::lock::ranked /// [mod]: crate::lock::ranked
pub struct RwLockWriteGuard<'a, T> { pub struct RwLockWriteGuard<'a, T> {
inner: parking_lot::RwLockWriteGuard<'a, T>, inner: parking_lot::RwLockWriteGuard<'a, T>,
saved: LockState, saved: LockStateGuard,
} }
impl<T> RwLock<T> { impl<T> RwLock<T> {
@ -253,7 +267,7 @@ impl<T> RwLock<T> {
let saved = acquire(self.rank, Location::caller()); let saved = acquire(self.rank, Location::caller());
RwLockReadGuard { RwLockReadGuard {
inner: self.inner.read(), inner: self.inner.read(),
saved, saved: LockStateGuard(saved),
} }
} }
@ -262,7 +276,7 @@ impl<T> RwLock<T> {
let saved = acquire(self.rank, Location::caller()); let saved = acquire(self.rank, Location::caller());
RwLockWriteGuard { RwLockWriteGuard {
inner: self.inner.write(), inner: self.inner.write(),
saved, saved: LockStateGuard(saved),
} }
} }
} }
@ -273,18 +287,6 @@ impl<T: std::fmt::Debug> std::fmt::Debug for RwLock<T> {
} }
} }
impl<'a, T> Drop for RwLockReadGuard<'a, T> {
fn drop(&mut self) {
release(self.saved);
}
}
impl<'a, T> Drop for RwLockWriteGuard<'a, T> {
fn drop(&mut self) {
release(self.saved);
}
}
impl<'a, T> std::ops::Deref for RwLockReadGuard<'a, T> { impl<'a, T> std::ops::Deref for RwLockReadGuard<'a, T> {
type Target = T; type Target = T;