parking_method/
reentrant_mutex_method.rs

1use crate::*;
2
3/// Trait for implementing read/write flavors on ReentantMutex.
4pub trait ReentrantMutexMethod<'a, V> {
5    /// Obtain a lock on a reentrant mutex. Blocking locks are infallible and always return a
6    /// 'Some()' variant.
7    fn lock(&self, mutex: &'a ReentrantMutex<V>) -> Option<ReentrantMutexGuard<'a, V>>;
8}
9
10macro_rules! impl_locking_method {
11    ($policy:ty, $lock:expr) => {
12        impl<'a, V> ReentrantMutexMethod<'a, V> for $policy {
13            #[inline(always)]
14            #[allow(unused_variables)]
15            fn lock(&self, mutex: &'a ReentrantMutex<V>) -> Option<ReentrantMutexGuard<'a, V>> {
16                #[allow(unused_macros)]
17                macro_rules! method {
18                    () => {
19                        self
20                    };
21                }
22                #[allow(unused_macros)]
23                macro_rules! lock {
24                    () => {
25                        mutex
26                    };
27                }
28                $lock
29            }
30        }
31    };
32}
33
34impl_locking_method!(Blocking, Some(lock!().lock()));
35
36impl_locking_method!(TryLock, lock!().try_lock());
37
38impl_locking_method!(Duration, lock!().try_lock_for(*method!()));
39
40impl_locking_method!(Instant, lock!().try_lock_until(*method!()));
41
42impl_locking_method!(Recursive<Blocking>, Some(lock!().lock()));
43
44impl_locking_method!(Recursive<TryLock>, lock!().try_lock());
45
46impl_locking_method!(Recursive<Duration>, lock!().try_lock_for(method!().0));
47
48impl_locking_method!(Recursive<Instant>, lock!().try_lock_until(method!().0));
49
50#[cfg(test)]
51mod test {
52    use crate::*;
53
54    #[test]
55    fn smoke() {
56        let mutex = ReentrantMutex::new(String::from("test"));
57        assert_eq!(
58            *ReentrantMutexMethod::lock(&Blocking, &mutex).unwrap(),
59            "test"
60        );
61    }
62
63    #[test]
64    fn trylocks() {
65        let mutex = ReentrantMutex::new(String::from("test"));
66
67        assert_eq!(
68            *ReentrantMutexMethod::lock(&TryLock, &mutex).unwrap(),
69            "test"
70        );
71        assert_eq!(
72            *ReentrantMutexMethod::lock(&Duration::from_millis(100), &mutex).unwrap(),
73            "test"
74        );
75        assert_eq!(
76            *ReentrantMutexMethod::lock(&(Instant::now() + Duration::from_millis(100)), &mutex)
77                .unwrap(),
78            "test"
79        );
80    }
81
82    #[test]
83    fn recursivelocks() {
84        let recmutex = ReentrantMutex::new(String::from("test"));
85
86        let guard = ReentrantMutexMethod::lock(&Blocking, &recmutex).unwrap();
87
88        assert_eq!(
89            *ReentrantMutexMethod::lock(&Recursive(Blocking), &recmutex).unwrap(),
90            "test"
91        );
92        assert_eq!(
93            *ReentrantMutexMethod::lock(&Recursive(TryLock), &recmutex).unwrap(),
94            "test"
95        );
96        assert_eq!(
97            *ReentrantMutexMethod::lock(&Recursive(Duration::from_millis(100)), &recmutex).unwrap(),
98            "test"
99        );
100        assert_eq!(
101            *ReentrantMutexMethod::lock(
102                &Recursive(Instant::now() + Duration::from_millis(100)),
103                &recmutex
104            )
105            .unwrap(),
106            "test"
107        );
108
109        drop(guard);
110    }
111}