1use std::{
2 fmt::Debug,
3 ops::{Deref, DerefMut},
4};
5
6#[cfg(feature = "lock_tracking")]
7mod tracking {
8 use super::*;
9 use crate::{Duration, Instant};
10 use std::collections::VecDeque;
11 use tracing::warn;
12
13 #[derive(Debug)]
14 struct Inner<T> {
15 last_lock_owner: VecDeque<(&'static str, Duration)>,
16 value: T,
17 }
18
19 pub(crate) struct Mutex<T> {
22 inner: std::sync::Mutex<Inner<T>>,
23 }
24
25 impl<T: Debug> Debug for Mutex<T> {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 Debug::fmt(&self.inner, f)
28 }
29 }
30
31 impl<T> Mutex<T> {
32 pub(crate) fn new(value: T) -> Self {
33 Self {
34 inner: std::sync::Mutex::new(Inner {
35 last_lock_owner: VecDeque::new(),
36 value,
37 }),
38 }
39 }
40
41 pub(crate) fn lock(&self, purpose: &'static str) -> MutexGuard<'_, T> {
45 let now = Instant::now();
48 let guard = self.inner.lock().unwrap();
49
50 let lock_time = Instant::now();
51 let elapsed = lock_time.duration_since(now);
52
53 if elapsed > Duration::from_millis(1) {
54 warn!(
55 "Locking the connection for {} took {:?}. Last owners: {:?}",
56 purpose, elapsed, guard.last_lock_owner
57 );
58 }
59
60 MutexGuard {
61 guard,
62 start_time: lock_time,
63 purpose,
64 }
65 }
66 }
67
68 pub(crate) struct MutexGuard<'a, T> {
69 guard: std::sync::MutexGuard<'a, Inner<T>>,
70 start_time: Instant,
71 purpose: &'static str,
72 }
73
74 impl<T> Drop for MutexGuard<'_, T> {
75 fn drop(&mut self) {
76 if self.guard.last_lock_owner.len() == MAX_LOCK_OWNERS {
77 self.guard.last_lock_owner.pop_back();
78 }
79
80 let duration = self.start_time.elapsed();
81
82 if duration > Duration::from_millis(1) {
83 warn!(
84 "Utilizing the connection for {} took {:?}",
85 self.purpose, duration
86 );
87 }
88
89 self.guard
90 .last_lock_owner
91 .push_front((self.purpose, duration));
92 }
93 }
94
95 impl<T> Deref for MutexGuard<'_, T> {
96 type Target = T;
97
98 fn deref(&self) -> &Self::Target {
99 &self.guard.value
100 }
101 }
102
103 impl<T> DerefMut for MutexGuard<'_, T> {
104 fn deref_mut(&mut self) -> &mut Self::Target {
105 &mut self.guard.value
106 }
107 }
108
109 const MAX_LOCK_OWNERS: usize = 20;
110}
111
112#[cfg(feature = "lock_tracking")]
113pub(crate) use tracking::{Mutex, MutexGuard};
114
115#[cfg(not(feature = "lock_tracking"))]
116mod non_tracking {
117 use super::*;
118
119 #[derive(Debug)]
122 pub(crate) struct Mutex<T> {
123 inner: std::sync::Mutex<T>,
124 }
125
126 impl<T> Mutex<T> {
127 pub(crate) fn new(value: T) -> Self {
128 Self {
129 inner: std::sync::Mutex::new(value),
130 }
131 }
132
133 pub(crate) fn lock(&self, _purpose: &'static str) -> MutexGuard<'_, T> {
137 MutexGuard {
138 guard: self.inner.lock().unwrap(),
139 }
140 }
141 }
142
143 pub(crate) struct MutexGuard<'a, T> {
144 guard: std::sync::MutexGuard<'a, T>,
145 }
146
147 impl<T> Deref for MutexGuard<'_, T> {
148 type Target = T;
149
150 fn deref(&self) -> &Self::Target {
151 self.guard.deref()
152 }
153 }
154
155 impl<T> DerefMut for MutexGuard<'_, T> {
156 fn deref_mut(&mut self) -> &mut Self::Target {
157 self.guard.deref_mut()
158 }
159 }
160}
161
162#[cfg(not(feature = "lock_tracking"))]
163pub(crate) use non_tracking::{Mutex, MutexGuard};