locktick/
std.rs

1use std::{
2    sync::{MutexGuard, PoisonError, RwLockReadGuard, RwLockWriteGuard, TryLockError},
3    time::Instant,
4};
5
6#[cfg(feature = "tracing")]
7use tracing::trace;
8
9use crate::lock_info::{call_location, GuardKind, Location, LockGuard, LockInfo, LockKind};
10
11#[derive(Debug)]
12pub struct Mutex<T> {
13    lock: std::sync::Mutex<T>,
14    location: Location,
15}
16
17impl<T> Mutex<T> {
18    pub fn new(item: T) -> Self {
19        Self {
20            lock: std::sync::Mutex::new(item),
21            location: LockInfo::register(LockKind::Mutex),
22        }
23    }
24
25    pub fn lock(&self) -> Result<LockGuard<MutexGuard<'_, T>>, PoisonError<MutexGuard<'_, T>>> {
26        let guard_kind = GuardKind::Lock;
27        let guard_location = call_location();
28        #[cfg(feature = "tracing")]
29        trace!("Acquiring a {:?} guard at {}", guard_kind, guard_location);
30        let timestamp = Instant::now();
31        let guard = self.lock.lock()?;
32        let wait_time = timestamp.elapsed();
33        Ok(LockGuard::new(
34            guard,
35            guard_kind,
36            &self.location,
37            guard_location,
38            wait_time,
39        ))
40    }
41
42    pub fn try_lock(
43        &self,
44    ) -> Result<LockGuard<MutexGuard<'_, T>>, TryLockError<MutexGuard<'_, T>>> {
45        let guard_kind = GuardKind::Lock;
46        let guard_location = call_location();
47        #[cfg(feature = "tracing")]
48        trace!(
49            "Attempting to acquire a {:?} guard at {}",
50            guard_kind,
51            self.location
52        );
53        let timestamp = Instant::now();
54        #[allow(clippy::map_identity)]
55        let guard = self.lock.try_lock().inspect_err(|_e| {
56            #[cfg(feature = "tracing")]
57            trace!(
58                "Failed to acquire a {:?} guard at {guard_location}: {_e}",
59                guard_kind,
60            );
61        })?;
62        let wait_time = timestamp.elapsed();
63        Ok(LockGuard::new(
64            guard,
65            guard_kind,
66            &self.location,
67            guard_location,
68            wait_time,
69        ))
70    }
71}
72
73impl<T: Default> Default for Mutex<T> {
74    fn default() -> Self {
75        Self {
76            lock: Default::default(),
77            location: LockInfo::register(LockKind::Mutex),
78        }
79    }
80}
81
82#[derive(Debug)]
83pub struct RwLock<T> {
84    lock: std::sync::RwLock<T>,
85    location: Location,
86}
87
88impl<T> RwLock<T> {
89    pub fn new(item: T) -> Self {
90        Self {
91            lock: std::sync::RwLock::new(item),
92            location: LockInfo::register(LockKind::RwLock),
93        }
94    }
95
96    pub fn read(
97        &self,
98    ) -> Result<LockGuard<RwLockReadGuard<'_, T>>, PoisonError<RwLockReadGuard<'_, T>>> {
99        let guard_kind = GuardKind::Read;
100        let guard_location = call_location();
101        #[cfg(feature = "tracing")]
102        trace!("Acquiring a {:?} guard at {}", guard_kind, guard_location);
103        let timestamp = Instant::now();
104        let guard = self.lock.read()?;
105        let wait_time = timestamp.elapsed();
106        Ok(LockGuard::new(
107            guard,
108            guard_kind,
109            &self.location,
110            guard_location,
111            wait_time,
112        ))
113    }
114
115    pub fn try_read(
116        &self,
117    ) -> Result<LockGuard<RwLockReadGuard<'_, T>>, TryLockError<RwLockReadGuard<'_, T>>> {
118        let guard_kind = GuardKind::Read;
119        let guard_location = call_location();
120        #[cfg(feature = "tracing")]
121        trace!(
122            "Attempting to acquire a {:?} guard at {}",
123            guard_kind,
124            guard_location
125        );
126        let timestamp = Instant::now();
127        let guard = self.lock.try_read().inspect_err(|_e| {
128            #[cfg(feature = "tracing")]
129            trace!(
130                "Failed to acquire a {:?} guard at {guard_location}: {_e}",
131                guard_kind,
132            );
133        })?;
134        let wait_time = timestamp.elapsed();
135        Ok(LockGuard::new(
136            guard,
137            guard_kind,
138            &self.location,
139            guard_location,
140            wait_time,
141        ))
142    }
143
144    pub fn write(
145        &self,
146    ) -> Result<LockGuard<RwLockWriteGuard<'_, T>>, PoisonError<RwLockWriteGuard<'_, T>>> {
147        let guard_kind = GuardKind::Write;
148        let guard_location = call_location();
149        #[cfg(feature = "tracing")]
150        trace!("Acquiring a {:?} guard at {}", guard_kind, guard_location);
151        let timestamp = Instant::now();
152        let guard = self.lock.write()?;
153        let wait_time = timestamp.elapsed();
154        Ok(LockGuard::new(
155            guard,
156            guard_kind,
157            &self.location,
158            guard_location,
159            wait_time,
160        ))
161    }
162
163    pub fn try_write(
164        &self,
165    ) -> Result<LockGuard<RwLockWriteGuard<'_, T>>, TryLockError<RwLockWriteGuard<'_, T>>> {
166        let guard_kind = GuardKind::Write;
167        let guard_location = call_location();
168        #[cfg(feature = "tracing")]
169        trace!(
170            "Attempting to acquire a {:?} guard at {}",
171            guard_kind,
172            guard_location
173        );
174        let timestamp = Instant::now();
175        let guard = self.lock.try_write().inspect_err(|_e| {
176            #[cfg(feature = "tracing")]
177            trace!(
178                "Failed to acquire a {:?} guard at {guard_location}: {_e}",
179                guard_kind,
180            );
181        })?;
182        let wait_time = timestamp.elapsed();
183        Ok(LockGuard::new(
184            guard,
185            guard_kind,
186            &self.location,
187            guard_location,
188            wait_time,
189        ))
190    }
191}
192
193impl<T: Default> Default for RwLock<T> {
194    fn default() -> Self {
195        Self {
196            lock: Default::default(),
197            location: LockInfo::register(LockKind::RwLock),
198        }
199    }
200}