|
1 | 1 | use crate::cell::{Cell, UnsafeCell}; |
2 | 2 | use crate::sync::atomic::{AtomicU8, Ordering}; |
3 | | -use crate::sync::mpsc::{channel, Sender}; |
| 3 | +use crate::sync::{Arc, Condvar, Mutex}; |
4 | 4 | use crate::thread::{self, LocalKey}; |
5 | 5 | use crate::thread_local; |
6 | 6 |
|
7 | | -struct Foo(Sender<()>); |
| 7 | +#[derive(Clone, Default)] |
| 8 | +struct Signal(Arc<(Mutex<bool>, Condvar)>); |
| 9 | + |
| 10 | +impl Signal { |
| 11 | + fn notify(&self) { |
| 12 | + let (set, cvar) = &*self.0; |
| 13 | + *set.lock().unwrap() = true; |
| 14 | + cvar.notify_one(); |
| 15 | + } |
| 16 | + |
| 17 | + fn wait(&self) { |
| 18 | + let (set, cvar) = &*self.0; |
| 19 | + let mut set = set.lock().unwrap(); |
| 20 | + while !*set { |
| 21 | + set = cvar.wait(set).unwrap(); |
| 22 | + } |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +struct Foo(Signal); |
8 | 27 |
|
9 | 28 | impl Drop for Foo { |
10 | 29 | fn drop(&mut self) { |
11 | | - let Foo(ref s) = *self; |
12 | | - s.send(()).unwrap(); |
| 30 | + let Foo(ref f) = *self; |
| 31 | + f.notify(); |
13 | 32 | } |
14 | 33 | } |
15 | 34 |
|
@@ -69,14 +88,15 @@ fn smoke_dtor() { |
69 | 88 | run(&FOO2); |
70 | 89 |
|
71 | 90 | fn run(key: &'static LocalKey<UnsafeCell<Option<Foo>>>) { |
72 | | - let (tx, rx) = channel(); |
| 91 | + let signal = Signal::default(); |
| 92 | + let signal2 = signal.clone(); |
73 | 93 | let t = thread::spawn(move || unsafe { |
74 | | - let mut tx = Some(tx); |
| 94 | + let mut signal = Some(signal2); |
75 | 95 | key.with(|f| { |
76 | | - *f.get() = Some(Foo(tx.take().unwrap())); |
| 96 | + *f.get() = Some(Foo(signal.take().unwrap())); |
77 | 97 | }); |
78 | 98 | }); |
79 | | - rx.recv().unwrap(); |
| 99 | + signal.wait(); |
80 | 100 | t.join().unwrap(); |
81 | 101 | } |
82 | 102 | } |
@@ -165,48 +185,50 @@ fn self_referential() { |
165 | 185 | // requires the destructor to be run to pass the test). |
166 | 186 | #[test] |
167 | 187 | fn dtors_in_dtors_in_dtors() { |
168 | | - struct S1(Sender<()>); |
| 188 | + struct S1(Signal); |
169 | 189 | thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None)); |
170 | 190 | thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell::new(None)); |
171 | 191 |
|
172 | 192 | impl Drop for S1 { |
173 | 193 | fn drop(&mut self) { |
174 | | - let S1(ref tx) = *self; |
| 194 | + let S1(ref signal) = *self; |
175 | 195 | unsafe { |
176 | | - let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone()))); |
| 196 | + let _ = K2.try_with(|s| *s.get() = Some(Foo(signal.clone()))); |
177 | 197 | } |
178 | 198 | } |
179 | 199 | } |
180 | 200 |
|
181 | | - let (tx, rx) = channel(); |
| 201 | + let signal = Signal::default(); |
| 202 | + let signal2 = signal.clone(); |
182 | 203 | let _t = thread::spawn(move || unsafe { |
183 | | - let mut tx = Some(tx); |
184 | | - K1.with(|s| *s.get() = Some(S1(tx.take().unwrap()))); |
| 204 | + let mut signal = Some(signal2); |
| 205 | + K1.with(|s| *s.get() = Some(S1(signal.take().unwrap()))); |
185 | 206 | }); |
186 | | - rx.recv().unwrap(); |
| 207 | + signal.wait(); |
187 | 208 | } |
188 | 209 |
|
189 | 210 | #[test] |
190 | 211 | fn dtors_in_dtors_in_dtors_const_init() { |
191 | | - struct S1(Sender<()>); |
| 212 | + struct S1(Signal); |
192 | 213 | thread_local!(static K1: UnsafeCell<Option<S1>> = const { UnsafeCell::new(None) }); |
193 | 214 | thread_local!(static K2: UnsafeCell<Option<Foo>> = const { UnsafeCell::new(None) }); |
194 | 215 |
|
195 | 216 | impl Drop for S1 { |
196 | 217 | fn drop(&mut self) { |
197 | | - let S1(ref tx) = *self; |
| 218 | + let S1(ref signal) = *self; |
198 | 219 | unsafe { |
199 | | - let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone()))); |
| 220 | + let _ = K2.try_with(|s| *s.get() = Some(Foo(signal.clone()))); |
200 | 221 | } |
201 | 222 | } |
202 | 223 | } |
203 | 224 |
|
204 | | - let (tx, rx) = channel(); |
| 225 | + let signal = Signal::default(); |
| 226 | + let signal2 = signal.clone(); |
205 | 227 | let _t = thread::spawn(move || unsafe { |
206 | | - let mut tx = Some(tx); |
207 | | - K1.with(|s| *s.get() = Some(S1(tx.take().unwrap()))); |
| 228 | + let mut signal = Some(signal2); |
| 229 | + K1.with(|s| *s.get() = Some(S1(signal.take().unwrap()))); |
208 | 230 | }); |
209 | | - rx.recv().unwrap(); |
| 231 | + signal.wait(); |
210 | 232 | } |
211 | 233 |
|
212 | 234 | // This test tests that TLS destructors have run before the thread joins. The |
|
0 commit comments