aboutsummaryrefslogtreecommitdiff
path: root/tests/atomic_waker.rs
blob: 5693bd01a1a8903d20a441422799fdf3551295e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#[cfg(feature = "executor")]
#[test]
fn basic() {
    use std::sync::atomic::AtomicUsize;
    use std::sync::atomic::Ordering;
    use std::sync::Arc;
    use std::thread;

    use futures::executor::block_on;
    use futures::future::poll_fn;
    use futures::task::{AtomicWaker, Poll};

    let atomic_waker = Arc::new(AtomicWaker::new());
    let atomic_waker_copy = atomic_waker.clone();

    let returned_pending = Arc::new(AtomicUsize::new(0));
    let returned_pending_copy = returned_pending.clone();

    let woken = Arc::new(AtomicUsize::new(0));
    let woken_copy = woken.clone();

    let t = thread::spawn(move || {
        let mut pending_count = 0;

        block_on(poll_fn(move |cx| {
            if woken_copy.load(Ordering::Relaxed) == 1 {
                Poll::Ready(())
            } else {
                // Assert we return pending exactly once
                assert_eq!(0, pending_count);
                pending_count += 1;
                atomic_waker_copy.register(cx.waker());

                returned_pending_copy.store(1, Ordering::Relaxed);

                Poll::Pending
            }
        }))
    });

    while returned_pending.load(Ordering::Relaxed) == 0 {}

    // give spawned thread some time to sleep in `block_on`
    thread::yield_now();

    woken.store(1, Ordering::Relaxed);
    atomic_waker.wake();

    t.join().unwrap();
}