cyfs_debug/check/
reentry_checked_mutex.rs1use super::tracker::*;
2
3use std::sync::{Arc, Mutex, MutexGuard, PoisonError, TryLockError};
4
5pub struct ReenterCheckedMutex<T> {
6 inner: Mutex<T>,
7 own_thread_id: Arc<Mutex<Option<std::thread::ThreadId>>>,
8}
9
10impl<T> ReenterCheckedMutex<T> {
11 pub fn new(t: T) -> ReenterCheckedMutex<T> {
12 ReenterCheckedMutex {
13 inner: Mutex::new(t),
14 own_thread_id: Arc::new(Mutex::new(None)),
15 }
16 }
17}
18
19type LockResult<'a, T> = Result<ReenterCheckedMutexGuard<'a, T>, PoisonError<MutexGuard<'a, T>>>;
20type TryLockResult<'a, T> = Result<ReenterCheckedMutexGuard<'a, T>, TryLockError<MutexGuard<'a, T>>>;
21
22impl<T> ReenterCheckedMutex<T> {
23 pub fn lock(&self) -> LockResult<'_, T> {
24
25 let current = std::thread::current().id();
26 {
28 let holder = self.own_thread_id.lock().unwrap();
29 assert_ne!(*holder, Some(current));
30 }
31
32 self.inner.lock().map(|lock| {
33
34 *self.own_thread_id.lock().unwrap() = Some(current);
35
36 ReenterCheckedMutexGuard::new(lock, self.own_thread_id.clone())
37 })
38 }
39
40 pub fn try_lock(&self) -> TryLockResult<'_, T> {
41 let current = std::thread::current().id();
42
43 match self.inner.try_lock() {
44 Ok(lock) => {
45
46 *self.own_thread_id.lock().unwrap() = Some(current);
47
48 let ret = ReenterCheckedMutexGuard::new(lock, self.own_thread_id.clone());
49
50 Ok(ret)
51 }
52 Err(e) => Err(e),
53 }
54 }
55
56 pub fn is_poisoned(&self) -> bool {
57 self.inner.is_poisoned()
58 }
59
60 pub fn into_inner(self) -> std::sync::LockResult<T>
61 where
62 T: Sized,
63 {
64 self.inner.into_inner()
65 }
66
67 pub fn get_mut(&mut self) -> std::sync::LockResult<&mut T> {
68 self.inner.get_mut()
69 }
70}
71
72use std::fmt;
73use std::ops::{Deref, DerefMut};
74
75pub struct ReenterCheckedMutexGuard<'a, T: ?Sized + 'a> {
76 inner: MutexGuard<'a, T>,
77 own_thread_id: Arc<Mutex<Option<std::thread::ThreadId>>>,
78 tracker: TimeoutTracker,
79}
80
81impl<'a, T: ?Sized> ReenterCheckedMutexGuard<'a, T> {
82 fn new(lock: MutexGuard<'a, T>, own_thread_id: Arc<Mutex<Option<std::thread::ThreadId>>>,) -> Self {
83 let time = chrono::Local::now().to_rfc3339();
84 let tracker =
85 TimeoutTracker::new(TimeoutTrackerCategory::Lock, time, std::time::Duration::from_secs(30));
86 Self { inner: lock, own_thread_id, tracker }
87 }
88}
89
90impl<T: ?Sized> Deref for ReenterCheckedMutexGuard<'_, T> {
91 type Target = T;
92
93 fn deref(&self) -> &T {
94 &*self.inner
95 }
96}
97
98impl<T: ?Sized> DerefMut for ReenterCheckedMutexGuard<'_, T> {
99 fn deref_mut(&mut self) -> &mut T {
100 &mut *self.inner
101 }
102}
103
104impl<T: ?Sized> Drop for ReenterCheckedMutexGuard<'_, T> {
105 #[inline]
106 fn drop(&mut self) {
107 if let Some(_t) = self.own_thread_id.lock().unwrap().take() {
108
109 } else {
110 unreachable!();
111 }
112 }
113}
114
115impl<T: ?Sized + fmt::Debug> fmt::Debug for ReenterCheckedMutexGuard<'_, T> {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 fmt::Debug::fmt(&**self, f)
118 }
119}
120
121impl<T: ?Sized + fmt::Display> fmt::Display for ReenterCheckedMutexGuard<'_, T> {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 (**self).fmt(f)
124 }
125}
126
127
128#[allow(dead_code)]
129#[macro_export]
130macro_rules! lock {
131 ($m:expr) => {
132 $m.lock()
133 };
134}
135
136#[allow(dead_code)]
137#[macro_export]
138macro_rules! try_lock {
139 ($m:expr) => {
140 $m.try_lock()
141 };
142}