]> git.proxmox.com Git - rustc.git/blob - vendor/crossbeam-utils/tests/thread.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / vendor / crossbeam-utils / tests / thread.rs
1 use std::any::Any;
2 use std::sync::atomic::{AtomicUsize, Ordering};
3 use std::thread::sleep;
4 use std::time::Duration;
5
6 use crossbeam_utils::thread;
7
8 const THREADS: usize = 10;
9 const SMALL_STACK_SIZE: usize = 20;
10
11 #[test]
12 fn join() {
13 let counter = AtomicUsize::new(0);
14 thread::scope(|scope| {
15 let handle = scope.spawn(|_| {
16 counter.store(1, Ordering::Relaxed);
17 });
18 assert!(handle.join().is_ok());
19
20 let panic_handle = scope.spawn(|_| {
21 panic!("\"My honey is running out!\", said Pooh.");
22 });
23 assert!(panic_handle.join().is_err());
24 })
25 .unwrap();
26
27 // There should be sufficient synchronization.
28 assert_eq!(1, counter.load(Ordering::Relaxed));
29 }
30
31 #[test]
32 fn counter() {
33 let counter = AtomicUsize::new(0);
34 thread::scope(|scope| {
35 for _ in 0..THREADS {
36 scope.spawn(|_| {
37 counter.fetch_add(1, Ordering::Relaxed);
38 });
39 }
40 })
41 .unwrap();
42
43 assert_eq!(THREADS, counter.load(Ordering::Relaxed));
44 }
45
46 #[test]
47 fn counter_builder() {
48 let counter = AtomicUsize::new(0);
49 thread::scope(|scope| {
50 for i in 0..THREADS {
51 scope
52 .builder()
53 .name(format!("child-{}", i))
54 .stack_size(SMALL_STACK_SIZE)
55 .spawn(|_| {
56 counter.fetch_add(1, Ordering::Relaxed);
57 })
58 .unwrap();
59 }
60 })
61 .unwrap();
62
63 assert_eq!(THREADS, counter.load(Ordering::Relaxed));
64 }
65
66 #[test]
67 fn counter_panic() {
68 let counter = AtomicUsize::new(0);
69 let result = thread::scope(|scope| {
70 scope.spawn(|_| {
71 panic!("\"My honey is running out!\", said Pooh.");
72 });
73 sleep(Duration::from_millis(100));
74
75 for _ in 0..THREADS {
76 scope.spawn(|_| {
77 counter.fetch_add(1, Ordering::Relaxed);
78 });
79 }
80 });
81
82 assert_eq!(THREADS, counter.load(Ordering::Relaxed));
83 assert!(result.is_err());
84 }
85
86 #[test]
87 fn panic_twice() {
88 let result = thread::scope(|scope| {
89 scope.spawn(|_| {
90 sleep(Duration::from_millis(500));
91 panic!("thread #1");
92 });
93 scope.spawn(|_| {
94 panic!("thread #2");
95 });
96 });
97
98 let err = result.unwrap_err();
99 let vec = err
100 .downcast_ref::<Vec<Box<dyn Any + Send + 'static>>>()
101 .unwrap();
102 assert_eq!(2, vec.len());
103
104 let first = vec[0].downcast_ref::<&str>().unwrap();
105 let second = vec[1].downcast_ref::<&str>().unwrap();
106 assert_eq!("thread #1", *first);
107 assert_eq!("thread #2", *second)
108 }
109
110 #[test]
111 fn panic_many() {
112 let result = thread::scope(|scope| {
113 scope.spawn(|_| panic!("deliberate panic #1"));
114 scope.spawn(|_| panic!("deliberate panic #2"));
115 scope.spawn(|_| panic!("deliberate panic #3"));
116 });
117
118 let err = result.unwrap_err();
119 let vec = err
120 .downcast_ref::<Vec<Box<dyn Any + Send + 'static>>>()
121 .unwrap();
122 assert_eq!(3, vec.len());
123
124 for panic in vec.iter() {
125 let panic = panic.downcast_ref::<&str>().unwrap();
126 assert!(
127 *panic == "deliberate panic #1"
128 || *panic == "deliberate panic #2"
129 || *panic == "deliberate panic #3"
130 );
131 }
132 }
133
134 #[test]
135 fn nesting() {
136 let var = "foo".to_string();
137
138 struct Wrapper<'a> {
139 var: &'a String,
140 }
141
142 impl<'a> Wrapper<'a> {
143 fn recurse(&'a self, scope: &thread::Scope<'a>, depth: usize) {
144 assert_eq!(self.var, "foo");
145
146 if depth > 0 {
147 scope.spawn(move |scope| {
148 self.recurse(scope, depth - 1);
149 });
150 }
151 }
152 }
153
154 let wrapper = Wrapper { var: &var };
155
156 thread::scope(|scope| {
157 scope.spawn(|scope| {
158 scope.spawn(|scope| {
159 wrapper.recurse(scope, 5);
160 });
161 });
162 })
163 .unwrap();
164 }
165
166 #[test]
167 fn join_nested() {
168 thread::scope(|scope| {
169 scope.spawn(|scope| {
170 let handle = scope.spawn(|_| 7);
171
172 sleep(Duration::from_millis(200));
173 handle.join().unwrap();
174 });
175
176 sleep(Duration::from_millis(100));
177 })
178 .unwrap();
179 }
180
181 #[test]
182 fn scope_returns_ok() {
183 let result = thread::scope(|scope| scope.spawn(|_| 1234).join().unwrap()).unwrap();
184 assert_eq!(result, 1234);
185 }
186
187 #[cfg(unix)]
188 #[test]
189 fn as_pthread_t() {
190 use std::os::unix::thread::JoinHandleExt;
191 thread::scope(|scope| {
192 let handle = scope.spawn(|_scope| {
193 sleep(Duration::from_millis(100));
194 42
195 });
196 let _pthread_t = handle.as_pthread_t();
197 handle.join().unwrap();
198 })
199 .unwrap();
200 }
201
202 #[cfg(windows)]
203 #[test]
204 fn as_raw_handle() {
205 use std::os::windows::io::AsRawHandle;
206 thread::scope(|scope| {
207 let handle = scope.spawn(|_scope| {
208 sleep(Duration::from_millis(100));
209 42
210 });
211 let _raw_handle = handle.as_raw_handle();
212 handle.join().unwrap();
213 })
214 .unwrap();
215 }