1#[cfg(any(feature = "parking_lot", feature = "tokio"))]
47use crate::locks::LockValue;
48
49#[cfg(any(feature = "parking_lot", feature = "tokio"))]
50use crate::lock_query::LockQuery;
51
52#[cfg(any(feature = "parking_lot", feature = "tokio"))]
53use crate::lock_lazy::LockLazyQuery;
54
55#[cfg(any(feature = "parking_lot", feature = "tokio"))]
56use crate::lock_join::LockJoinQuery;
57
58#[cfg(any(feature = "parking_lot", feature = "tokio"))]
59use std::collections::HashMap;
60
61#[cfg(any(feature = "parking_lot", feature = "tokio"))]
62use std::sync::Arc;
63
64#[cfg(feature = "parking_lot")]
86#[derive(Clone, Debug)]
87pub struct ParkingLotRwLockWrapper<T>(Arc<parking_lot::RwLock<T>>);
88
89#[cfg(feature = "parking_lot")]
90impl<T> ParkingLotRwLockWrapper<T> {
91 pub fn new(value: T) -> Self {
93 Self(Arc::new(parking_lot::RwLock::new(value)))
94 }
95
96 pub fn inner(&self) -> &Arc<parking_lot::RwLock<T>> {
98 &self.0
99 }
100}
101
102#[cfg(feature = "parking_lot")]
103impl<T> LockValue<T> for ParkingLotRwLockWrapper<T> {
104 fn with_value<F, R>(&self, f: F) -> Option<R>
105 where
106 F: FnOnce(&T) -> R,
107 {
108 let guard = self.0.read();
110 Some(f(&*guard))
111 }
112}
113
114#[cfg(feature = "parking_lot")]
116#[derive(Clone, Debug)]
117pub struct ParkingLotMutexWrapper<T>(Arc<parking_lot::Mutex<T>>);
118
119#[cfg(feature = "parking_lot")]
120impl<T> ParkingLotMutexWrapper<T> {
121 pub fn new(value: T) -> Self {
123 Self(Arc::new(parking_lot::Mutex::new(value)))
124 }
125
126 pub fn inner(&self) -> &Arc<parking_lot::Mutex<T>> {
128 &self.0
129 }
130}
131
132#[cfg(feature = "parking_lot")]
133impl<T> LockValue<T> for ParkingLotMutexWrapper<T> {
134 fn with_value<F, R>(&self, f: F) -> Option<R>
135 where
136 F: FnOnce(&T) -> R,
137 {
138 let guard = self.0.lock();
140 Some(f(&*guard))
141 }
142}
143
144#[cfg(feature = "parking_lot")]
149pub trait ParkingLotQueryExt<V> {
150 fn lock_query(&self) -> LockQuery<'_, V, ParkingLotRwLockWrapper<V>>;
152
153 fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotRwLockWrapper<V>, impl Iterator<Item = &ParkingLotRwLockWrapper<V>>>;
155}
156
157#[cfg(feature = "parking_lot")]
158impl<K, V: 'static> ParkingLotQueryExt<V> for HashMap<K, ParkingLotRwLockWrapper<V>>
159where
160 K: std::hash::Hash + Eq,
161{
162 fn lock_query(&self) -> LockQuery<'_, V, ParkingLotRwLockWrapper<V>> {
163 let locks: Vec<_> = self.values().collect();
164 LockQuery::from_locks(locks)
165 }
166
167 fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotRwLockWrapper<V>, impl Iterator<Item = &ParkingLotRwLockWrapper<V>>> {
168 LockLazyQuery::new(self.values())
169 }
170}
171
172#[cfg(feature = "parking_lot")]
174pub trait ParkingLotMutexQueryExt<V> {
175 fn lock_query(&self) -> LockQuery<'_, V, ParkingLotMutexWrapper<V>>;
177
178 fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotMutexWrapper<V>, impl Iterator<Item = &ParkingLotMutexWrapper<V>>>;
180}
181
182#[cfg(feature = "parking_lot")]
183impl<K, V: 'static> ParkingLotMutexQueryExt<V> for HashMap<K, ParkingLotMutexWrapper<V>>
184where
185 K: std::hash::Hash + Eq,
186{
187 fn lock_query(&self) -> LockQuery<'_, V, ParkingLotMutexWrapper<V>> {
188 let locks: Vec<_> = self.values().collect();
189 LockQuery::from_locks(locks)
190 }
191
192 fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotMutexWrapper<V>, impl Iterator<Item = &ParkingLotMutexWrapper<V>>> {
193 LockLazyQuery::new(self.values())
194 }
195}
196
197#[cfg(feature = "parking_lot")]
201pub trait ParkingLotJoinExt<V> {
202 fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, ParkingLotRwLockWrapper<R>>)
204 -> LockJoinQuery<'a, V, R, ParkingLotRwLockWrapper<V>, ParkingLotRwLockWrapper<R>>
205 where
206 R: 'static;
207}
208
209#[cfg(feature = "parking_lot")]
210impl<K, V: 'static> ParkingLotJoinExt<V> for HashMap<K, ParkingLotRwLockWrapper<V>>
211where
212 K: std::hash::Hash + Eq,
213{
214 fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, ParkingLotRwLockWrapper<R>>)
215 -> LockJoinQuery<'a, V, R, ParkingLotRwLockWrapper<V>, ParkingLotRwLockWrapper<R>>
216 where
217 R: 'static,
218 {
219 let left_locks: Vec<_> = self.values().collect();
220 let right_locks: Vec<_> = right.values().collect();
221 LockJoinQuery::new(left_locks, right_locks)
222 }
223}
224
225#[cfg(feature = "parking_lot")]
227pub trait ParkingLotMutexJoinExt<V> {
228 fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, ParkingLotMutexWrapper<R>>)
230 -> LockJoinQuery<'a, V, R, ParkingLotMutexWrapper<V>, ParkingLotMutexWrapper<R>>
231 where
232 R: 'static;
233}
234
235#[cfg(feature = "parking_lot")]
236impl<K, V: 'static> ParkingLotMutexJoinExt<V> for HashMap<K, ParkingLotMutexWrapper<V>>
237where
238 K: std::hash::Hash + Eq,
239{
240 fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, ParkingLotMutexWrapper<R>>)
241 -> LockJoinQuery<'a, V, R, ParkingLotMutexWrapper<V>, ParkingLotMutexWrapper<R>>
242 where
243 R: 'static,
244 {
245 let left_locks: Vec<_> = self.values().collect();
246 let right_locks: Vec<_> = right.values().collect();
247 LockJoinQuery::new(left_locks, right_locks)
248 }
249}
250
251#[cfg(feature = "tokio")]
271#[derive(Clone, Debug)]
272pub struct TokioRwLockWrapper<T>(Arc<tokio::sync::RwLock<T>>);
273
274#[cfg(feature = "tokio")]
275impl<T> TokioRwLockWrapper<T> {
276 pub fn new(value: T) -> Self {
278 Self(Arc::new(tokio::sync::RwLock::new(value)))
279 }
280
281 pub fn inner(&self) -> &Arc<tokio::sync::RwLock<T>> {
283 &self.0
284 }
285}
286
287#[cfg(feature = "tokio")]
288impl<T> LockValue<T> for TokioRwLockWrapper<T> {
289 fn with_value<F, R>(&self, f: F) -> Option<R>
290 where
291 F: FnOnce(&T) -> R,
292 {
293 let guard = self.0.blocking_read();
296 Some(f(&*guard))
297 }
298}
299
300#[cfg(feature = "tokio")]
302#[derive(Clone, Debug)]
303pub struct TokioMutexWrapper<T>(Arc<tokio::sync::Mutex<T>>);
304
305#[cfg(feature = "tokio")]
306impl<T> TokioMutexWrapper<T> {
307 pub fn new(value: T) -> Self {
309 Self(Arc::new(tokio::sync::Mutex::new(value)))
310 }
311
312 pub fn inner(&self) -> &Arc<tokio::sync::Mutex<T>> {
314 &self.0
315 }
316}
317
318#[cfg(feature = "tokio")]
319impl<T> LockValue<T> for TokioMutexWrapper<T> {
320 fn with_value<F, R>(&self, f: F) -> Option<R>
321 where
322 F: FnOnce(&T) -> R,
323 {
324 let guard = self.0.blocking_lock();
326 Some(f(&*guard))
327 }
328}
329
330#[cfg(feature = "tokio")]
335pub trait TokioLockQueryExt<V> {
336 fn lock_query(&self) -> LockQuery<'_, V, TokioRwLockWrapper<V>>;
338
339 fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, TokioRwLockWrapper<V>, impl Iterator<Item = &TokioRwLockWrapper<V>>>;
341}
342
343#[cfg(feature = "tokio")]
344impl<K, V: 'static> TokioLockQueryExt<V> for HashMap<K, TokioRwLockWrapper<V>>
345where
346 K: std::hash::Hash + Eq,
347{
348 fn lock_query(&self) -> LockQuery<'_, V, TokioRwLockWrapper<V>> {
349 let locks: Vec<_> = self.values().collect();
350 LockQuery::from_locks(locks)
351 }
352
353 fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, TokioRwLockWrapper<V>, impl Iterator<Item = &TokioRwLockWrapper<V>>> {
354 LockLazyQuery::new(self.values())
355 }
356}
357
358#[cfg(feature = "tokio")]
360pub trait TokioMutexQueryExt<V> {
361 fn lock_query(&self) -> LockQuery<'_, V, TokioMutexWrapper<V>>;
363
364 fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, TokioMutexWrapper<V>, impl Iterator<Item = &TokioMutexWrapper<V>>>;
366}
367
368#[cfg(feature = "tokio")]
369impl<K, V: 'static> TokioMutexQueryExt<V> for HashMap<K, TokioMutexWrapper<V>>
370where
371 K: std::hash::Hash + Eq,
372{
373 fn lock_query(&self) -> LockQuery<'_, V, TokioMutexWrapper<V>> {
374 let locks: Vec<_> = self.values().collect();
375 LockQuery::from_locks(locks)
376 }
377
378 fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, TokioMutexWrapper<V>, impl Iterator<Item = &TokioMutexWrapper<V>>> {
379 LockLazyQuery::new(self.values())
380 }
381}
382
383#[cfg(feature = "tokio")]
387pub trait TokioLockJoinExt<V> {
388 fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, TokioRwLockWrapper<R>>)
390 -> LockJoinQuery<'a, V, R, TokioRwLockWrapper<V>, TokioRwLockWrapper<R>>
391 where
392 R: 'static;
393}
394
395#[cfg(feature = "tokio")]
396impl<K, V: 'static> TokioLockJoinExt<V> for HashMap<K, TokioRwLockWrapper<V>>
397where
398 K: std::hash::Hash + Eq,
399{
400 fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, TokioRwLockWrapper<R>>)
401 -> LockJoinQuery<'a, V, R, TokioRwLockWrapper<V>, TokioRwLockWrapper<R>>
402 where
403 R: 'static,
404 {
405 let left_locks: Vec<_> = self.values().collect();
406 let right_locks: Vec<_> = right.values().collect();
407 LockJoinQuery::new(left_locks, right_locks)
408 }
409}
410
411#[cfg(feature = "tokio")]
413pub trait TokioMutexJoinExt<V> {
414 fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, TokioMutexWrapper<R>>)
416 -> LockJoinQuery<'a, V, R, TokioMutexWrapper<V>, TokioMutexWrapper<R>>
417 where
418 R: 'static;
419}
420
421#[cfg(feature = "tokio")]
422impl<K, V: 'static> TokioMutexJoinExt<V> for HashMap<K, TokioMutexWrapper<V>>
423where
424 K: std::hash::Hash + Eq,
425{
426 fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, TokioMutexWrapper<R>>)
427 -> LockJoinQuery<'a, V, R, TokioMutexWrapper<V>, TokioMutexWrapper<R>>
428 where
429 R: 'static,
430 {
431 let left_locks: Vec<_> = self.values().collect();
432 let right_locks: Vec<_> = right.values().collect();
433 LockJoinQuery::new(left_locks, right_locks)
434 }
435}
436
437#[cfg(test)]
438mod tests {
439 use super::*;
440
441 #[cfg(feature = "parking_lot")]
442 #[test]
443 fn test_parking_lot_wrapper() {
444 let wrapper = ParkingLotRwLockWrapper::new(42);
445 let result = wrapper.with_value(|v| *v * 2);
446 assert_eq!(result, Some(84));
447 }
448
449 #[cfg(feature = "tokio")]
450 #[test]
451 fn test_tokio_wrapper() {
452 let wrapper = TokioRwLockWrapper::new(42);
453 let result = wrapper.with_value(|v| *v * 2);
454 assert_eq!(result, Some(84));
455 }
456}
457