zenith_foundation/
sync.rs1use std::sync::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
9
10#[inline]
20pub fn lock_recover<T>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
21 mutex.lock().unwrap_or_else(|e| e.into_inner())
22}
23
24#[inline]
29pub fn read_recover<T>(lock: &RwLock<T>) -> RwLockReadGuard<'_, T> {
30 lock.read().unwrap_or_else(|e| e.into_inner())
31}
32
33#[inline]
35pub fn write_recover<T>(lock: &RwLock<T>) -> RwLockWriteGuard<'_, T> {
36 lock.write().unwrap_or_else(|e| e.into_inner())
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use std::sync::Arc;
43
44 #[test]
45 fn test_lock_recover_normal() {
46 let m = Mutex::new(42u64);
47 {
48 let mut g = lock_recover(&m);
49 *g += 1;
50 }
51 assert_eq!(*lock_recover(&m), 43);
52 }
53
54 #[test]
55 fn test_lock_recover_poisoned() {
56 let m = Arc::new(Mutex::new(1u64));
57 let m2 = Arc::clone(&m);
58 let _ = std::thread::spawn(move || {
60 let mut g = m2.lock().expect("首次加锁应成功");
61 *g = 99;
62 panic!("intentional poison for test");
63 })
64 .join();
65 assert_eq!(*lock_recover(&m), 99);
67 }
68}