]> git.proxmox.com Git - rustc.git/blame - library/std/src/sync/rwlock/tests.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / library / std / src / sync / rwlock / tests.rs
CommitLineData
1b1a35ee
XL
1use crate::sync::atomic::{AtomicUsize, Ordering};
2use crate::sync::mpsc::channel;
064997fb 3use crate::sync::{Arc, RwLock, RwLockReadGuard, TryLockError};
1b1a35ee
XL
4use crate::thread;
5use rand::{self, Rng};
6
7#[derive(Eq, PartialEq, Debug)]
8struct NonCopy(i32);
9
10#[test]
11fn smoke() {
12 let l = RwLock::new(());
13 drop(l.read().unwrap());
14 drop(l.write().unwrap());
15 drop((l.read().unwrap(), l.read().unwrap()));
16 drop(l.write().unwrap());
17}
18
19#[test]
20fn frob() {
21 const N: u32 = 10;
f2b60f7d 22 const M: usize = if cfg!(miri) { 100 } else { 1000 };
1b1a35ee
XL
23
24 let r = Arc::new(RwLock::new(()));
25
26 let (tx, rx) = channel::<()>();
27 for _ in 0..N {
28 let tx = tx.clone();
29 let r = r.clone();
30 thread::spawn(move || {
31 let mut rng = rand::thread_rng();
32 for _ in 0..M {
33 if rng.gen_bool(1.0 / (N as f64)) {
34 drop(r.write().unwrap());
35 } else {
36 drop(r.read().unwrap());
37 }
38 }
39 drop(tx);
40 });
41 }
42 drop(tx);
43 let _ = rx.recv();
44}
45
46#[test]
47fn test_rw_arc_poison_wr() {
48 let arc = Arc::new(RwLock::new(1));
49 let arc2 = arc.clone();
50 let _: Result<(), _> = thread::spawn(move || {
51 let _lock = arc2.write().unwrap();
52 panic!();
53 })
54 .join();
55 assert!(arc.read().is_err());
56}
57
58#[test]
59fn test_rw_arc_poison_ww() {
60 let arc = Arc::new(RwLock::new(1));
61 assert!(!arc.is_poisoned());
62 let arc2 = arc.clone();
63 let _: Result<(), _> = thread::spawn(move || {
64 let _lock = arc2.write().unwrap();
65 panic!();
66 })
67 .join();
68 assert!(arc.write().is_err());
69 assert!(arc.is_poisoned());
70}
71
72#[test]
73fn test_rw_arc_no_poison_rr() {
74 let arc = Arc::new(RwLock::new(1));
75 let arc2 = arc.clone();
76 let _: Result<(), _> = thread::spawn(move || {
77 let _lock = arc2.read().unwrap();
78 panic!();
79 })
80 .join();
81 let lock = arc.read().unwrap();
82 assert_eq!(*lock, 1);
83}
84#[test]
85fn test_rw_arc_no_poison_rw() {
86 let arc = Arc::new(RwLock::new(1));
87 let arc2 = arc.clone();
88 let _: Result<(), _> = thread::spawn(move || {
89 let _lock = arc2.read().unwrap();
90 panic!()
91 })
92 .join();
93 let lock = arc.write().unwrap();
94 assert_eq!(*lock, 1);
95}
96
97#[test]
98fn test_rw_arc() {
99 let arc = Arc::new(RwLock::new(0));
100 let arc2 = arc.clone();
101 let (tx, rx) = channel();
102
103 thread::spawn(move || {
104 let mut lock = arc2.write().unwrap();
105 for _ in 0..10 {
106 let tmp = *lock;
107 *lock = -1;
108 thread::yield_now();
109 *lock = tmp + 1;
110 }
111 tx.send(()).unwrap();
112 });
113
114 // Readers try to catch the writer in the act
115 let mut children = Vec::new();
116 for _ in 0..5 {
117 let arc3 = arc.clone();
118 children.push(thread::spawn(move || {
119 let lock = arc3.read().unwrap();
120 assert!(*lock >= 0);
121 }));
122 }
123
124 // Wait for children to pass their asserts
125 for r in children {
126 assert!(r.join().is_ok());
127 }
128
129 // Wait for writer to finish
130 rx.recv().unwrap();
131 let lock = arc.read().unwrap();
132 assert_eq!(*lock, 10);
133}
134
135#[test]
136fn test_rw_arc_access_in_unwind() {
137 let arc = Arc::new(RwLock::new(1));
138 let arc2 = arc.clone();
139 let _ = thread::spawn(move || -> () {
140 struct Unwinder {
141 i: Arc<RwLock<isize>>,
142 }
143 impl Drop for Unwinder {
144 fn drop(&mut self) {
145 let mut lock = self.i.write().unwrap();
146 *lock += 1;
147 }
148 }
149 let _u = Unwinder { i: arc2 };
150 panic!();
151 })
152 .join();
153 let lock = arc.read().unwrap();
154 assert_eq!(*lock, 2);
155}
156
157#[test]
158fn test_rwlock_unsized() {
159 let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
160 {
161 let b = &mut *rw.write().unwrap();
162 b[0] = 4;
163 b[2] = 5;
164 }
165 let comp: &[i32] = &[4, 2, 5];
166 assert_eq!(&*rw.read().unwrap(), comp);
167}
168
169#[test]
170fn test_rwlock_try_write() {
171 let lock = RwLock::new(0isize);
172 let read_guard = lock.read().unwrap();
173
174 let write_result = lock.try_write();
175 match write_result {
176 Err(TryLockError::WouldBlock) => (),
177 Ok(_) => assert!(false, "try_write should not succeed while read_guard is in scope"),
178 Err(_) => assert!(false, "unexpected error"),
179 }
180
181 drop(read_guard);
182}
183
184#[test]
185fn test_into_inner() {
186 let m = RwLock::new(NonCopy(10));
187 assert_eq!(m.into_inner().unwrap(), NonCopy(10));
188}
189
190#[test]
191fn test_into_inner_drop() {
192 struct Foo(Arc<AtomicUsize>);
193 impl Drop for Foo {
194 fn drop(&mut self) {
195 self.0.fetch_add(1, Ordering::SeqCst);
196 }
197 }
198 let num_drops = Arc::new(AtomicUsize::new(0));
199 let m = RwLock::new(Foo(num_drops.clone()));
200 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
201 {
202 let _inner = m.into_inner().unwrap();
203 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
204 }
205 assert_eq!(num_drops.load(Ordering::SeqCst), 1);
206}
207
208#[test]
209fn test_into_inner_poison() {
210 let m = Arc::new(RwLock::new(NonCopy(10)));
211 let m2 = m.clone();
212 let _ = thread::spawn(move || {
213 let _lock = m2.write().unwrap();
214 panic!("test panic in inner thread to poison RwLock");
215 })
216 .join();
217
218 assert!(m.is_poisoned());
219 match Arc::try_unwrap(m).unwrap().into_inner() {
220 Err(e) => assert_eq!(e.into_inner(), NonCopy(10)),
5e7ed085 221 Ok(x) => panic!("into_inner of poisoned RwLock is Ok: {x:?}"),
1b1a35ee
XL
222 }
223}
224
225#[test]
226fn test_get_mut() {
227 let mut m = RwLock::new(NonCopy(10));
228 *m.get_mut().unwrap() = NonCopy(20);
229 assert_eq!(m.into_inner().unwrap(), NonCopy(20));
230}
231
232#[test]
233fn test_get_mut_poison() {
234 let m = Arc::new(RwLock::new(NonCopy(10)));
235 let m2 = m.clone();
236 let _ = thread::spawn(move || {
237 let _lock = m2.write().unwrap();
238 panic!("test panic in inner thread to poison RwLock");
239 })
240 .join();
241
242 assert!(m.is_poisoned());
243 match Arc::try_unwrap(m).unwrap().get_mut() {
244 Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)),
5e7ed085 245 Ok(x) => panic!("get_mut of poisoned RwLock is Ok: {x:?}"),
1b1a35ee
XL
246 }
247}
064997fb
FG
248
249#[test]
250fn test_read_guard_covariance() {
251 fn do_stuff<'a>(_: RwLockReadGuard<'_, &'a i32>, _: &'a i32) {}
252 let j: i32 = 5;
253 let lock = RwLock::new(&j);
254 {
255 let i = 6;
256 do_stuff(lock.read().unwrap(), &i);
257 }
258 drop(lock);
259}