1#[cfg(feature = "production")]
7use parking_lot::Mutex as ParkingLotMutex;
8
9#[cfg(not(feature = "production"))]
10use std::sync::Mutex as StdMutex;
11
12#[cfg(feature = "production")]
26pub type Mutex<T> = ParkingLotMutex<T>;
27
28#[cfg(not(feature = "production"))]
30pub type Mutex<T> = StdMutex<T>;
31
32#[cfg(feature = "production")]
46pub fn lock<T>(mutex: &Mutex<T>) -> parking_lot::MutexGuard<'_, T> {
47 mutex.lock()
48}
49
50#[cfg(not(feature = "production"))]
52pub fn lock<T>(mutex: &Mutex<T>) -> std::sync::MutexGuard<'_, T> {
53 mutex.lock().unwrap_or_else(|e| e.into_inner())
54}
55
56#[cfg(feature = "production")]
78pub fn try_lock<T>(mutex: &Mutex<T>) -> crate::Result<parking_lot::MutexGuard<'_, T>> {
79 mutex
80 .try_lock()
81 .ok_or_else(|| crate::Error::Retrieval("Mutex lock failed: would block".to_string()))
82}
83
84#[cfg(not(feature = "production"))]
86pub fn try_lock<T>(mutex: &Mutex<T>) -> crate::Result<std::sync::MutexGuard<'_, T>> {
87 mutex.try_lock().map_err(|e| match e {
88 std::sync::TryLockError::Poisoned(poison) => {
89 crate::Error::Retrieval(format!("Mutex lock failed: poisoned - {}", poison))
90 }
91 std::sync::TryLockError::WouldBlock => {
92 crate::Error::Retrieval("Mutex lock failed: would block".to_string())
93 }
94 })
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_mutex_new_and_lock() {
103 let mutex = Mutex::new(42);
104 let guard = lock(&mutex);
105 assert_eq!(*guard, 42);
106 }
107
108 #[test]
109 fn test_mutex_modify_value() {
110 let mutex = Mutex::new(0);
111 {
112 let mut guard = lock(&mutex);
113 *guard = 100;
114 }
115 let guard = lock(&mutex);
116 assert_eq!(*guard, 100);
117 }
118
119 #[test]
120 fn test_try_lock_success() {
121 let mutex = Mutex::new("test");
122 let result = try_lock(&mutex);
123 assert!(result.is_ok());
124 assert_eq!(*result.unwrap(), "test");
125 }
126
127 #[test]
128 fn test_mutex_with_struct() {
129 #[derive(Debug, PartialEq)]
130 struct Data {
131 value: i32,
132 name: String,
133 }
134
135 let mutex = Mutex::new(Data {
136 value: 42,
137 name: "test".to_string(),
138 });
139
140 let guard = lock(&mutex);
141 assert_eq!(guard.value, 42);
142 assert_eq!(guard.name, "test");
143 }
144
145 #[test]
146 fn test_multiple_locks_sequential() {
147 let mutex = Mutex::new(0);
148
149 for i in 0..10 {
150 let mut guard = lock(&mutex);
151 *guard = i;
152 }
153
154 let guard = lock(&mutex);
155 assert_eq!(*guard, 9);
156 }
157
158 #[test]
159 fn test_try_lock_returns_correct_value() {
160 let mutex = Mutex::new(vec![1, 2, 3]);
161
162 let result = try_lock(&mutex);
164 match result {
165 Ok(guard) => {
166 assert_eq!(guard.len(), 3);
167 assert_eq!(guard[0], 1);
168 }
169 Err(_) => {
170 panic!("try_lock should succeed when not contested");
171 }
172 }
173 }
174}