use std::sync::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
#[inline]
pub(crate) fn lock<T>(m: &Mutex<T>) -> MutexGuard<'_, T> {
m.lock().unwrap_or_else(|e| e.into_inner())
}
#[inline]
#[allow(dead_code)] pub(crate) fn rwlock_read<T>(m: &RwLock<T>) -> RwLockReadGuard<'_, T> {
m.read().unwrap_or_else(|e| e.into_inner())
}
#[inline]
#[allow(dead_code)] pub(crate) fn rwlock_write<T>(m: &RwLock<T>) -> RwLockWriteGuard<'_, T> {
m.write().unwrap_or_else(|e| e.into_inner())
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
use std::thread;
#[test]
fn lock_recovers_from_mutex_poison() {
let m = Arc::new(Mutex::new(7u32));
let m2 = Arc::clone(&m);
let _ = thread::spawn(move || {
let _guard = m2.lock().expect("first lock must succeed");
panic!("poison the mutex");
})
.join();
let guard = lock(&m);
assert_eq!(*guard, 7);
}
#[test]
fn rwlock_helpers_recover_from_poison() {
let m = Arc::new(RwLock::new(11u32));
let m2 = Arc::clone(&m);
let _ = thread::spawn(move || {
let _guard = m2.write().expect("first write must succeed");
panic!("poison the rwlock");
})
.join();
assert_eq!(*rwlock_read(&m), 11);
{
let mut g = rwlock_write(&m);
*g = 42;
}
assert_eq!(*rwlock_read(&m), 42);
}
}