parking_method/
readlock_method.rs

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