cyfs_debug/check/
reentry_checked_mutex.rs

1use 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        // debug!("try enter mutex: {:?}", current);
27        {
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}