1use std::sync::{Arc, Mutex, MutexGuard};
2use std::sync::atomic::AtomicU64;
3use std::time::Duration;
4use once_cell::sync::Lazy;
5
6pub static GLOBAL_STD_TIMEOUT: Lazy<Arc<AtomicU64>> = Lazy::new(|| Arc::new(AtomicU64::new(5)));
7
8pub struct MutexWithTimeout<T> {
10 inner: Mutex<T>,
11 timeout: Duration,
12}
13
14impl<T> MutexWithTimeout<T> {
15 pub fn new(inner: T) -> Self {
17 Self {
18 inner: Mutex::new(inner),
19 timeout: Duration::from_secs(GLOBAL_STD_TIMEOUT.load(std::sync::atomic::Ordering::Relaxed)),
20 }
21 }
22
23 pub fn new_with_timeout(inner: T, timeout: Duration) -> Self {
25 Self {
26 inner: Mutex::new(inner),
27 timeout,
28 }
29 }
30
31
32 pub fn lock(&self) -> Option<MutexGuard<T>> {
35 let start = std::time::Instant::now();
36 loop {
37 if let Ok(guard) = self.inner.try_lock() {
38 return Some(guard);
39 }
40
41 if start.elapsed() > self.timeout {
42 break;
43 }
44 }
45 None
46 }
47
48 pub fn try_lock(&self) -> Option<std::sync::MutexGuard<T>> {
50 self.inner.try_lock().ok()
51 }
52}