Skip to main content

sofie_core/
unpoisoned.rs

1//! A panic while a lock was held must not fail every later caller of the lock.
2
3use std::sync::{Mutex, MutexGuard, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
4
5pub fn lock<T: ?Sized>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
6    mutex.lock().unwrap_or_else(PoisonError::into_inner)
7}
8
9pub fn read<T: ?Sized>(lock: &RwLock<T>) -> RwLockReadGuard<'_, T> {
10    lock.read().unwrap_or_else(PoisonError::into_inner)
11}
12
13pub fn write<T: ?Sized>(lock: &RwLock<T>) -> RwLockWriteGuard<'_, T> {
14    lock.write().unwrap_or_else(PoisonError::into_inner)
15}
16
17#[cfg(test)]
18mod tests {
19    use super::*;
20
21    #[test]
22    fn a_lock_a_panic_poisoned_still_hands_out_its_value() {
23        let mutex = Mutex::new(1);
24        let rw = RwLock::new(2);
25        let _ = std::panic::catch_unwind(|| {
26            let _held = (lock(&mutex), write(&rw));
27            panic!("poisoning both");
28        });
29
30        assert!(mutex.is_poisoned() && rw.is_poisoned());
31        assert_eq!(*lock(&mutex), 1);
32        assert_eq!(*read(&rw), 2);
33        assert_eq!(*write(&rw), 2);
34    }
35}