]> git.proxmox.com Git - rustc.git/blob - library/std/src/sync/mutex/tests.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / library / std / src / sync / mutex / tests.rs
1 use crate::sync::atomic::{AtomicUsize, Ordering};
2 use crate::sync::mpsc::channel;
3 use crate::sync::{Arc, Condvar, Mutex};
4 use crate::thread;
5
6 struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
7
8 #[derive(Eq, PartialEq, Debug)]
9 struct NonCopy(i32);
10
11 #[test]
12 fn smoke() {
13 let m = Mutex::new(());
14 drop(m.lock().unwrap());
15 drop(m.lock().unwrap());
16 }
17
18 #[test]
19 fn lots_and_lots() {
20 const J: u32 = 1000;
21 const K: u32 = 3;
22
23 let m = Arc::new(Mutex::new(0));
24
25 fn inc(m: &Mutex<u32>) {
26 for _ in 0..J {
27 *m.lock().unwrap() += 1;
28 }
29 }
30
31 let (tx, rx) = channel();
32 for _ in 0..K {
33 let tx2 = tx.clone();
34 let m2 = m.clone();
35 thread::spawn(move || {
36 inc(&m2);
37 tx2.send(()).unwrap();
38 });
39 let tx2 = tx.clone();
40 let m2 = m.clone();
41 thread::spawn(move || {
42 inc(&m2);
43 tx2.send(()).unwrap();
44 });
45 }
46
47 drop(tx);
48 for _ in 0..2 * K {
49 rx.recv().unwrap();
50 }
51 assert_eq!(*m.lock().unwrap(), J * K * 2);
52 }
53
54 #[test]
55 fn try_lock() {
56 let m = Mutex::new(());
57 *m.try_lock().unwrap() = ();
58 }
59
60 #[test]
61 fn test_into_inner() {
62 let m = Mutex::new(NonCopy(10));
63 assert_eq!(m.into_inner().unwrap(), NonCopy(10));
64 }
65
66 #[test]
67 fn test_into_inner_drop() {
68 struct Foo(Arc<AtomicUsize>);
69 impl Drop for Foo {
70 fn drop(&mut self) {
71 self.0.fetch_add(1, Ordering::SeqCst);
72 }
73 }
74 let num_drops = Arc::new(AtomicUsize::new(0));
75 let m = Mutex::new(Foo(num_drops.clone()));
76 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
77 {
78 let _inner = m.into_inner().unwrap();
79 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
80 }
81 assert_eq!(num_drops.load(Ordering::SeqCst), 1);
82 }
83
84 #[test]
85 fn test_into_inner_poison() {
86 let m = Arc::new(Mutex::new(NonCopy(10)));
87 let m2 = m.clone();
88 let _ = thread::spawn(move || {
89 let _lock = m2.lock().unwrap();
90 panic!("test panic in inner thread to poison mutex");
91 })
92 .join();
93
94 assert!(m.is_poisoned());
95 match Arc::try_unwrap(m).unwrap().into_inner() {
96 Err(e) => assert_eq!(e.into_inner(), NonCopy(10)),
97 Ok(x) => panic!("into_inner of poisoned Mutex is Ok: {x:?}"),
98 }
99 }
100
101 #[test]
102 fn test_get_mut() {
103 let mut m = Mutex::new(NonCopy(10));
104 *m.get_mut().unwrap() = NonCopy(20);
105 assert_eq!(m.into_inner().unwrap(), NonCopy(20));
106 }
107
108 #[test]
109 fn test_get_mut_poison() {
110 let m = Arc::new(Mutex::new(NonCopy(10)));
111 let m2 = m.clone();
112 let _ = thread::spawn(move || {
113 let _lock = m2.lock().unwrap();
114 panic!("test panic in inner thread to poison mutex");
115 })
116 .join();
117
118 assert!(m.is_poisoned());
119 match Arc::try_unwrap(m).unwrap().get_mut() {
120 Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)),
121 Ok(x) => panic!("get_mut of poisoned Mutex is Ok: {x:?}"),
122 }
123 }
124
125 #[test]
126 fn test_mutex_arc_condvar() {
127 let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
128 let packet2 = Packet(packet.0.clone());
129 let (tx, rx) = channel();
130 let _t = thread::spawn(move || {
131 // wait until parent gets in
132 rx.recv().unwrap();
133 let &(ref lock, ref cvar) = &*packet2.0;
134 let mut lock = lock.lock().unwrap();
135 *lock = true;
136 cvar.notify_one();
137 });
138
139 let &(ref lock, ref cvar) = &*packet.0;
140 let mut lock = lock.lock().unwrap();
141 tx.send(()).unwrap();
142 assert!(!*lock);
143 while !*lock {
144 lock = cvar.wait(lock).unwrap();
145 }
146 }
147
148 #[test]
149 fn test_arc_condvar_poison() {
150 let packet = Packet(Arc::new((Mutex::new(1), Condvar::new())));
151 let packet2 = Packet(packet.0.clone());
152 let (tx, rx) = channel();
153
154 let _t = thread::spawn(move || -> () {
155 rx.recv().unwrap();
156 let &(ref lock, ref cvar) = &*packet2.0;
157 let _g = lock.lock().unwrap();
158 cvar.notify_one();
159 // Parent should fail when it wakes up.
160 panic!();
161 });
162
163 let &(ref lock, ref cvar) = &*packet.0;
164 let mut lock = lock.lock().unwrap();
165 tx.send(()).unwrap();
166 while *lock == 1 {
167 match cvar.wait(lock) {
168 Ok(l) => {
169 lock = l;
170 assert_eq!(*lock, 1);
171 }
172 Err(..) => break,
173 }
174 }
175 }
176
177 #[test]
178 fn test_mutex_arc_poison() {
179 let arc = Arc::new(Mutex::new(1));
180 assert!(!arc.is_poisoned());
181 let arc2 = arc.clone();
182 let _ = thread::spawn(move || {
183 let lock = arc2.lock().unwrap();
184 assert_eq!(*lock, 2);
185 })
186 .join();
187 assert!(arc.lock().is_err());
188 assert!(arc.is_poisoned());
189 }
190
191 #[test]
192 fn test_mutex_arc_nested() {
193 // Tests nested mutexes and access
194 // to underlying data.
195 let arc = Arc::new(Mutex::new(1));
196 let arc2 = Arc::new(Mutex::new(arc));
197 let (tx, rx) = channel();
198 let _t = thread::spawn(move || {
199 let lock = arc2.lock().unwrap();
200 let lock2 = lock.lock().unwrap();
201 assert_eq!(*lock2, 1);
202 tx.send(()).unwrap();
203 });
204 rx.recv().unwrap();
205 }
206
207 #[test]
208 fn test_mutex_arc_access_in_unwind() {
209 let arc = Arc::new(Mutex::new(1));
210 let arc2 = arc.clone();
211 let _ = thread::spawn(move || -> () {
212 struct Unwinder {
213 i: Arc<Mutex<i32>>,
214 }
215 impl Drop for Unwinder {
216 fn drop(&mut self) {
217 *self.i.lock().unwrap() += 1;
218 }
219 }
220 let _u = Unwinder { i: arc2 };
221 panic!();
222 })
223 .join();
224 let lock = arc.lock().unwrap();
225 assert_eq!(*lock, 2);
226 }
227
228 #[test]
229 fn test_mutex_unsized() {
230 let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
231 {
232 let b = &mut *mutex.lock().unwrap();
233 b[0] = 4;
234 b[2] = 5;
235 }
236 let comp: &[i32] = &[4, 2, 5];
237 assert_eq!(&*mutex.lock().unwrap(), comp);
238 }