Auto merge of #97924 - cuviper:unguarded-poison, r=Mark-Simulacrum

Avoid `thread::panicking()` in non-poisoning methods of `Mutex` and `RwLock`

`Mutex::lock()` and `RwLock::write()` are poison-guarded against panics,
in that they set the poison flag if a panic occurs while they're locked.
But if we're already in a panic (`thread::panicking()`), they leave the
poison flag alone.

That check is a bit of a waste for methods that never set the poison
flag though, namely `get_mut()`, `into_inner()`, and `RwLock::read()`.
These use-cases are now split to avoid that unnecessary call.
This commit is contained in:
bors 2022-06-18 15:18:50 +00:00
commit ec21d7ea3c
3 changed files with 15 additions and 8 deletions

View File

@ -423,7 +423,7 @@ pub fn into_inner(self) -> LockResult<T>
T: Sized,
{
let data = self.data.into_inner();
poison::map_result(self.poison.borrow(), |_| data)
poison::map_result(self.poison.borrow(), |()| data)
}
/// Returns a mutable reference to the underlying data.
@ -448,7 +448,7 @@ pub fn into_inner(self) -> LockResult<T>
#[stable(feature = "mutex_get_mut", since = "1.6.0")]
pub fn get_mut(&mut self) -> LockResult<&mut T> {
let data = self.data.get_mut();
poison::map_result(self.poison.borrow(), |_| data)
poison::map_result(self.poison.borrow(), |()| data)
}
}
@ -497,7 +497,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
poison::map_result(lock.poison.borrow(), |guard| MutexGuard { lock, poison: guard })
poison::map_result(lock.poison.guard(), |guard| MutexGuard { lock, poison: guard })
}
}

View File

@ -23,8 +23,15 @@ pub const fn new() -> Flag {
Flag { failed: AtomicBool::new(false) }
}
/// Check the flag for an unguarded borrow, where we only care about existing poison.
#[inline]
pub fn borrow(&self) -> LockResult<Guard> {
pub fn borrow(&self) -> LockResult<()> {
if self.get() { Err(PoisonError::new(())) } else { Ok(()) }
}
/// Check the flag for a guarded borrow, where we may also set poison when `done`.
#[inline]
pub fn guard(&self) -> LockResult<Guard> {
let ret = Guard { panicking: thread::panicking() };
if self.get() { Err(PoisonError::new(ret)) } else { Ok(ret) }
}

View File

@ -434,7 +434,7 @@ pub fn into_inner(self) -> LockResult<T>
T: Sized,
{
let data = self.data.into_inner();
poison::map_result(self.poison.borrow(), |_| data)
poison::map_result(self.poison.borrow(), |()| data)
}
/// Returns a mutable reference to the underlying data.
@ -461,7 +461,7 @@ pub fn into_inner(self) -> LockResult<T>
#[stable(feature = "rwlock_get_mut", since = "1.6.0")]
pub fn get_mut(&mut self) -> LockResult<&mut T> {
let data = self.data.get_mut();
poison::map_result(self.poison.borrow(), |_| data)
poison::map_result(self.poison.borrow(), |()| data)
}
}
@ -510,13 +510,13 @@ fn from(t: T) -> Self {
impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockReadGuard<'rwlock, T>> {
poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard { lock })
poison::map_result(lock.poison.borrow(), |()| RwLockReadGuard { lock })
}
}
impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> {
poison::map_result(lock.poison.borrow(), |guard| RwLockWriteGuard { lock, poison: guard })
poison::map_result(lock.poison.guard(), |guard| RwLockWriteGuard { lock, poison: guard })
}
}