]> git.lizzy.rs Git - rust.git/blob - library/std/src/sync/condvar/tests.rs
Rollup merge of #104512 - jyn514:download-ci-llvm-default, r=Mark-Simulacrum
[rust.git] / library / std / src / sync / condvar / tests.rs
1 use crate::sync::atomic::{AtomicBool, Ordering};
2 use crate::sync::mpsc::channel;
3 use crate::sync::{Arc, Condvar, Mutex};
4 use crate::thread;
5 use crate::time::Duration;
6
7 #[test]
8 fn smoke() {
9     let c = Condvar::new();
10     c.notify_one();
11     c.notify_all();
12 }
13
14 #[test]
15 #[cfg_attr(target_os = "emscripten", ignore)]
16 fn notify_one() {
17     let m = Arc::new(Mutex::new(()));
18     let m2 = m.clone();
19     let c = Arc::new(Condvar::new());
20     let c2 = c.clone();
21
22     let g = m.lock().unwrap();
23     let _t = thread::spawn(move || {
24         let _g = m2.lock().unwrap();
25         c2.notify_one();
26     });
27     let g = c.wait(g).unwrap();
28     drop(g);
29 }
30
31 #[test]
32 #[cfg_attr(target_os = "emscripten", ignore)]
33 fn notify_all() {
34     const N: usize = 10;
35
36     let data = Arc::new((Mutex::new(0), Condvar::new()));
37     let (tx, rx) = channel();
38     for _ in 0..N {
39         let data = data.clone();
40         let tx = tx.clone();
41         thread::spawn(move || {
42             let &(ref lock, ref cond) = &*data;
43             let mut cnt = lock.lock().unwrap();
44             *cnt += 1;
45             if *cnt == N {
46                 tx.send(()).unwrap();
47             }
48             while *cnt != 0 {
49                 cnt = cond.wait(cnt).unwrap();
50             }
51             tx.send(()).unwrap();
52         });
53     }
54     drop(tx);
55
56     let &(ref lock, ref cond) = &*data;
57     rx.recv().unwrap();
58     let mut cnt = lock.lock().unwrap();
59     *cnt = 0;
60     cond.notify_all();
61     drop(cnt);
62
63     for _ in 0..N {
64         rx.recv().unwrap();
65     }
66 }
67
68 #[test]
69 #[cfg_attr(target_os = "emscripten", ignore)]
70 fn wait_while() {
71     let pair = Arc::new((Mutex::new(false), Condvar::new()));
72     let pair2 = pair.clone();
73
74     // Inside of our lock, spawn a new thread, and then wait for it to start.
75     thread::spawn(move || {
76         let &(ref lock, ref cvar) = &*pair2;
77         let mut started = lock.lock().unwrap();
78         *started = true;
79         // We notify the condvar that the value has changed.
80         cvar.notify_one();
81     });
82
83     // Wait for the thread to start up.
84     let &(ref lock, ref cvar) = &*pair;
85     let guard = cvar.wait_while(lock.lock().unwrap(), |started| !*started);
86     assert!(*guard.unwrap());
87 }
88
89 #[test]
90 #[cfg_attr(target_os = "emscripten", ignore)]
91 fn wait_timeout_wait() {
92     let m = Arc::new(Mutex::new(()));
93     let c = Arc::new(Condvar::new());
94
95     loop {
96         let g = m.lock().unwrap();
97         let (_g, no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap();
98         // spurious wakeups mean this isn't necessarily true
99         // so execute test again, if not timeout
100         if !no_timeout.timed_out() {
101             continue;
102         }
103
104         break;
105     }
106 }
107
108 #[test]
109 #[cfg_attr(target_os = "emscripten", ignore)]
110 fn wait_timeout_while_wait() {
111     let m = Arc::new(Mutex::new(()));
112     let c = Arc::new(Condvar::new());
113
114     let g = m.lock().unwrap();
115     let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(1), |_| true).unwrap();
116     // no spurious wakeups. ensure it timed-out
117     assert!(wait.timed_out());
118 }
119
120 #[test]
121 #[cfg_attr(target_os = "emscripten", ignore)]
122 fn wait_timeout_while_instant_satisfy() {
123     let m = Arc::new(Mutex::new(()));
124     let c = Arc::new(Condvar::new());
125
126     let g = m.lock().unwrap();
127     let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(0), |_| false).unwrap();
128     // ensure it didn't time-out even if we were not given any time.
129     assert!(!wait.timed_out());
130 }
131
132 #[test]
133 #[cfg_attr(target_os = "emscripten", ignore)]
134 fn wait_timeout_while_wake() {
135     let pair = Arc::new((Mutex::new(false), Condvar::new()));
136     let pair_copy = pair.clone();
137
138     let &(ref m, ref c) = &*pair;
139     let g = m.lock().unwrap();
140     let _t = thread::spawn(move || {
141         let &(ref lock, ref cvar) = &*pair_copy;
142         let mut started = lock.lock().unwrap();
143         thread::sleep(Duration::from_millis(1));
144         *started = true;
145         cvar.notify_one();
146     });
147     let (g2, wait) = c
148         .wait_timeout_while(g, Duration::from_millis(u64::MAX), |&mut notified| !notified)
149         .unwrap();
150     // ensure it didn't time-out even if we were not given any time.
151     assert!(!wait.timed_out());
152     assert!(*g2);
153 }
154
155 #[test]
156 #[cfg_attr(target_os = "emscripten", ignore)]
157 fn wait_timeout_wake() {
158     let m = Arc::new(Mutex::new(()));
159     let c = Arc::new(Condvar::new());
160
161     loop {
162         let g = m.lock().unwrap();
163
164         let c2 = c.clone();
165         let m2 = m.clone();
166
167         let notified = Arc::new(AtomicBool::new(false));
168         let notified_copy = notified.clone();
169
170         let t = thread::spawn(move || {
171             let _g = m2.lock().unwrap();
172             thread::sleep(Duration::from_millis(1));
173             notified_copy.store(true, Ordering::SeqCst);
174             c2.notify_one();
175         });
176         let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u64::MAX)).unwrap();
177         assert!(!timeout_res.timed_out());
178         // spurious wakeups mean this isn't necessarily true
179         // so execute test again, if not notified
180         if !notified.load(Ordering::SeqCst) {
181             t.join().unwrap();
182             continue;
183         }
184         drop(g);
185
186         t.join().unwrap();
187
188         break;
189     }
190 }