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}