wrap Mutex and Condvar to handle poison

This centralizes a major source of `.unwrap()` throughout the code,
and one that would otherwise grow with upcoming changes. The new
error message should be more clear.
This commit is contained in:
Scott Lamb
2025-04-03 08:36:56 -07:00
parent 2903b680df
commit 0ccc6d0769
8 changed files with 120 additions and 62 deletions

View File

@@ -14,3 +14,64 @@ pub use crate::error::{Error, ErrorBuilder, ErrorKind, ResultExt};
pub use ahash::RandomState;
pub type FastHashMap<K, V> = std::collections::HashMap<K, V, ahash::RandomState>;
pub type FastHashSet<K> = std::collections::HashSet<K, ahash::RandomState>;
const NOT_POISONED: &str =
"not poisoned; this is a consequence of an earlier panic while holding this mutex; see logs.";
/// [`std::sync::Mutex`] wrapper which always panics on encountering poison.
#[derive(Default)]
pub struct Mutex<T>(std::sync::Mutex<T>);
impl<T> Mutex<T> {
#[inline]
pub const fn new(value: T) -> Self {
Mutex(std::sync::Mutex::new(value))
}
#[track_caller]
#[inline]
pub fn lock(&self) -> std::sync::MutexGuard<T> {
self.0.lock().expect(NOT_POISONED)
}
#[track_caller]
#[inline]
pub fn into_inner(self) -> T {
self.0.into_inner().expect(NOT_POISONED)
}
}
/// [`std::sync::Condvar`] wrapper which always panics on encountering poison.
#[derive(Default)]
pub struct Condvar(std::sync::Condvar);
impl Condvar {
#[inline]
pub const fn new() -> Self {
Self(std::sync::Condvar::new())
}
#[track_caller]
#[inline]
pub fn wait_timeout_while<'a, T, F>(
&self,
guard: std::sync::MutexGuard<'a, T>,
dur: std::time::Duration,
condition: F,
) -> (std::sync::MutexGuard<'a, T>, std::sync::WaitTimeoutResult)
where
F: FnMut(&mut T) -> bool,
{
self.0
.wait_timeout_while(guard, dur, condition)
.expect(NOT_POISONED)
}
}
impl std::ops::Deref for Condvar {
type Target = std::sync::Condvar;
fn deref(&self) -> &Self::Target {
&self.0
}
}