parking_lot/
recursive_rwlock.rs1use crate::RawRwLockRecursive;
2
3pub type RecursiveRwLock<T> = lock_api::RwLock<RawRwLockRecursive, T>;
20
21pub type RecursiveRwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLockRecursive, T>;
23
24pub type RecursiveRwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawRwLockRecursive, T>;
26
27pub type RecursiveRwLockUpgradableReadGuard<'a, T> =
29 lock_api::RwLockUpgradableReadGuard<'a, RawRwLockRecursive, T>;
30
31pub type MappedRecursiveRwLockReadGuard<'a, T> =
33 lock_api::MappedRwLockReadGuard<'a, RawRwLockRecursive, T>;
34
35pub type MappedRecursiveRwLockWriteGuard<'a, T> =
37 lock_api::MappedRwLockWriteGuard<'a, RawRwLockRecursive, T>;
38
39#[cfg(test)]
40mod tests {
41 use crate::{RecursiveRwLock, RecursiveRwLockReadGuard, RecursiveRwLockUpgradableReadGuard};
42 use rand::RngExt;
43 use std::sync::Arc;
44 use std::thread;
45
46 #[test]
47 fn frob() {
48 const N: u32 = 10;
49 const M: u32 = if cfg!(miri) { 100 } else { 1000 };
50
51 let lock = Arc::new(RecursiveRwLock::new(()));
52 let mut threads = Vec::new();
53 for _ in 0..N {
54 let lock = Arc::clone(&lock);
55 threads.push(thread::spawn(move || {
56 let mut rng = rand::rng();
57 for _ in 0..M {
58 if rng.random_bool(1.0 / N as f64) {
59 drop(lock.write());
60 } else {
61 drop(lock.read());
62 }
63 }
64 }));
65 }
66 for thread in threads {
67 thread.join().unwrap();
68 }
69 }
70
71 #[test]
72 fn recursive_read_with_waiting_writer() {
73 let lock = Arc::new(RecursiveRwLock::new(()));
74 let first = lock.read();
75 let second = lock.read();
76
77 let lock2 = Arc::clone(&lock);
78 let writer = thread::spawn(move || drop(lock2.write()));
79 while !unsafe { lock.raw() }.has_parked_threads() {
80 thread::yield_now();
81 }
82
83 assert!(lock.try_read().is_some());
84 let mut second = second;
85 RecursiveRwLockReadGuard::bump(&mut second);
86
87 drop(first);
88 drop(second);
89 writer.join().unwrap();
90 }
91
92 #[test]
93 fn upgrade() {
94 let lock = RecursiveRwLock::new(1);
95 let upgradable = lock.upgradable_read();
96 let read = lock.read();
97 drop(read);
98 let mut write = RecursiveRwLockUpgradableReadGuard::upgrade(upgradable);
99 *write = 2;
100 drop(write);
101 assert_eq!(*lock.read(), 2);
102 }
103}