Skip to main content

yapi_types/
sync.rs

1//! Locking that outlives a panic.
2
3use std::sync::{Mutex, MutexGuard, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
4
5/// Locks `mutex`, taking the data even when a panicking thread poisoned it.
6pub fn lock<T>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
7    mutex.lock().unwrap_or_else(PoisonError::into_inner)
8}
9
10/// Read-locks `lock`, taking the data even when a panicking thread poisoned it.
11pub fn read<T>(lock: &RwLock<T>) -> RwLockReadGuard<'_, T> {
12    lock.read().unwrap_or_else(PoisonError::into_inner)
13}
14
15/// Write-locks `lock`, taking the data even when a panicking thread poisoned it.
16pub fn write<T>(lock: &RwLock<T>) -> RwLockWriteGuard<'_, T> {
17    lock.write().unwrap_or_else(PoisonError::into_inner)
18}
19
20#[cfg(test)]
21mod tests {
22    use super::*;
23
24    #[test]
25    fn recovers_poisoned_rw_locks() {
26        let lock = RwLock::new(1);
27        let _ = std::panic::catch_unwind(|| {
28            let _guard = lock.write();
29            panic!("poison");
30        });
31        assert!(lock.is_poisoned());
32        *write(&lock) += 1;
33        assert_eq!(*read(&lock), 2);
34    }
35}