|
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