]> git.proxmox.com Git - rustc.git/blob - vendor/crossbeam-utils/tests/sharded_lock.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / vendor / crossbeam-utils / tests / sharded_lock.rs
1 extern crate crossbeam_utils;
2 extern crate rand;
3
4 use std::sync::mpsc::channel;
5 use std::thread;
6 use std::sync::{Arc, TryLockError};
7 use std::sync::atomic::{AtomicUsize, Ordering};
8
9 use crossbeam_utils::sync::ShardedLock;
10 use rand::Rng;
11
12 #[derive(Eq, PartialEq, Debug)]
13 struct NonCopy(i32);
14
15 #[test]
16 fn smoke() {
17 let l = ShardedLock::new(());
18 drop(l.read().unwrap());
19 drop(l.write().unwrap());
20 drop((l.read().unwrap(), l.read().unwrap()));
21 drop(l.write().unwrap());
22 }
23
24 #[test]
25 fn frob() {
26 const N: u32 = 10;
27 const M: usize = 1000;
28
29 let r = Arc::new(ShardedLock::new(()));
30
31 let (tx, rx) = channel::<()>();
32 for _ in 0..N {
33 let tx = tx.clone();
34 let r = r.clone();
35 thread::spawn(move || {
36 let mut rng = rand::thread_rng();
37 for _ in 0..M {
38 if rng.gen_bool(1.0 / (N as f64)) {
39 drop(r.write().unwrap());
40 } else {
41 drop(r.read().unwrap());
42 }
43 }
44 drop(tx);
45 });
46 }
47 drop(tx);
48 let _ = rx.recv();
49 }
50
51 #[test]
52 fn arc_poison_wr() {
53 let arc = Arc::new(ShardedLock::new(1));
54 let arc2 = arc.clone();
55 let _: Result<(), _> = thread::spawn(move || {
56 let _lock = arc2.write().unwrap();
57 panic!();
58 }).join();
59 assert!(arc.read().is_err());
60 }
61
62 #[test]
63 fn arc_poison_ww() {
64 let arc = Arc::new(ShardedLock::new(1));
65 assert!(!arc.is_poisoned());
66 let arc2 = arc.clone();
67 let _: Result<(), _> = thread::spawn(move || {
68 let _lock = arc2.write().unwrap();
69 panic!();
70 }).join();
71 assert!(arc.write().is_err());
72 assert!(arc.is_poisoned());
73 }
74
75 #[test]
76 fn arc_no_poison_rr() {
77 let arc = Arc::new(ShardedLock::new(1));
78 let arc2 = arc.clone();
79 let _: Result<(), _> = thread::spawn(move || {
80 let _lock = arc2.read().unwrap();
81 panic!();
82 }).join();
83 let lock = arc.read().unwrap();
84 assert_eq!(*lock, 1);
85 }
86 #[test]
87 fn arc_no_poison_sl() {
88 let arc = Arc::new(ShardedLock::new(1));
89 let arc2 = arc.clone();
90 let _: Result<(), _> = thread::spawn(move || {
91 let _lock = arc2.read().unwrap();
92 panic!()
93 }).join();
94 let lock = arc.write().unwrap();
95 assert_eq!(*lock, 1);
96 }
97
98 #[test]
99 fn arc() {
100 let arc = Arc::new(ShardedLock::new(0));
101 let arc2 = arc.clone();
102 let (tx, rx) = channel();
103
104 thread::spawn(move || {
105 let mut lock = arc2.write().unwrap();
106 for _ in 0..10 {
107 let tmp = *lock;
108 *lock = -1;
109 thread::yield_now();
110 *lock = tmp + 1;
111 }
112 tx.send(()).unwrap();
113 });
114
115 // Readers try to catch the writer in the act
116 let mut children = Vec::new();
117 for _ in 0..5 {
118 let arc3 = arc.clone();
119 children.push(thread::spawn(move || {
120 let lock = arc3.read().unwrap();
121 assert!(*lock >= 0);
122 }));
123 }
124
125 // Wait for children to pass their asserts
126 for r in children {
127 assert!(r.join().is_ok());
128 }
129
130 // Wait for writer to finish
131 rx.recv().unwrap();
132 let lock = arc.read().unwrap();
133 assert_eq!(*lock, 10);
134 }
135
136 #[test]
137 fn arc_access_in_unwind() {
138 let arc = Arc::new(ShardedLock::new(1));
139 let arc2 = arc.clone();
140 let _ = thread::spawn(move || -> () {
141 struct Unwinder {
142 i: Arc<ShardedLock<isize>>,
143 }
144 impl Drop for Unwinder {
145 fn drop(&mut self) {
146 let mut lock = self.i.write().unwrap();
147 *lock += 1;
148 }
149 }
150 let _u = Unwinder { i: arc2 };
151 panic!();
152 }).join();
153 let lock = arc.read().unwrap();
154 assert_eq!(*lock, 2);
155 }
156
157 #[test]
158 fn unsized_type() {
159 let sl: &ShardedLock<[i32]> = &ShardedLock::new([1, 2, 3]);
160 {
161 let b = &mut *sl.write().unwrap();
162 b[0] = 4;
163 b[2] = 5;
164 }
165 let comp: &[i32] = &[4, 2, 5];
166 assert_eq!(&*sl.read().unwrap(), comp);
167 }
168
169 #[test]
170 fn try_write() {
171 let lock = ShardedLock::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]
185 fn test_into_inner() {
186 let m = ShardedLock::new(NonCopy(10));
187 assert_eq!(m.into_inner().unwrap(), NonCopy(10));
188 }
189
190 #[test]
191 fn 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 = ShardedLock::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]
209 fn test_into_inner_poison() {
210 let m = Arc::new(ShardedLock::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 ShardedLock");
215 }).join();
216
217 assert!(m.is_poisoned());
218 match Arc::try_unwrap(m).unwrap().into_inner() {
219 Err(e) => assert_eq!(e.into_inner(), NonCopy(10)),
220 Ok(x) => panic!("into_inner of poisoned ShardedLock is Ok: {:?}", x),
221 }
222 }
223
224 #[test]
225 fn test_get_mut() {
226 let mut m = ShardedLock::new(NonCopy(10));
227 *m.get_mut().unwrap() = NonCopy(20);
228 assert_eq!(m.into_inner().unwrap(), NonCopy(20));
229 }
230
231 #[test]
232 fn test_get_mut_poison() {
233 let m = Arc::new(ShardedLock::new(NonCopy(10)));
234 let m2 = m.clone();
235 let _ = thread::spawn(move || {
236 let _lock = m2.write().unwrap();
237 panic!("test panic in inner thread to poison ShardedLock");
238 }).join();
239
240 assert!(m.is_poisoned());
241 match Arc::try_unwrap(m).unwrap().get_mut() {
242 Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)),
243 Ok(x) => panic!("get_mut of poisoned ShardedLock is Ok: {:?}", x),
244 }
245 }