1 use futures::executor::block_on;
2 use futures::future::poll_fn;
3 use futures::task::{AtomicWaker, Poll};
4 use std::sync::atomic::AtomicUsize;
5 use std::sync::atomic::Ordering;
6 use std::sync::Arc;
7 use std::thread;
8 
9 #[cfg_attr(miri, ignore)] // Miri is too slow
10 #[test]
basic()11 fn basic() {
12     let atomic_waker = Arc::new(AtomicWaker::new());
13     let atomic_waker_copy = atomic_waker.clone();
14 
15     let returned_pending = Arc::new(AtomicUsize::new(0));
16     let returned_pending_copy = returned_pending.clone();
17 
18     let woken = Arc::new(AtomicUsize::new(0));
19     let woken_copy = woken.clone();
20 
21     let t = thread::spawn(move || {
22         let mut pending_count = 0;
23 
24         block_on(poll_fn(move |cx| {
25             if woken_copy.load(Ordering::Relaxed) == 1 {
26                 Poll::Ready(())
27             } else {
28                 // Assert we return pending exactly once
29                 assert_eq!(0, pending_count);
30                 pending_count += 1;
31                 atomic_waker_copy.register(cx.waker());
32 
33                 returned_pending_copy.store(1, Ordering::Relaxed);
34 
35                 Poll::Pending
36             }
37         }))
38     });
39 
40     while returned_pending.load(Ordering::Relaxed) == 0 {}
41 
42     // give spawned thread some time to sleep in `block_on`
43     thread::yield_now();
44 
45     woken.store(1, Ordering::Relaxed);
46     atomic_waker.wake();
47 
48     t.join().unwrap();
49 }
50