use std::future::Future;
use std::pin::Pin;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
use super::atomic_waker::AtomicWaker;
use super::global::CallBackState;
use super::GLOBAL;
const DONE: usize = 1;
const WORKING: usize = 0;
pub struct Delay {
state: Arc<AtomicUsize>,
waker: Arc<AtomicWaker>,
}
impl Delay {
pub fn new(dur: Duration) -> Delay {
let delay = Delay {
state: Arc::new(WORKING.into()),
waker: Arc::new(AtomicWaker::new()),
};
let state = delay.state.clone();
let waker = delay.waker.clone();
GLOBAL.register(
Instant::now() + dur,
Box::new(move || {
state.store(DONE, Ordering::Release);
waker.wake();
CallBackState::None
}),
);
delay
}
}
impl Future for Delay {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.state.load(Ordering::Acquire) {
DONE => Poll::Ready(()),
WORKING => {
self.waker.register(cx.waker());
Poll::Pending
}
_ => unreachable!(),
}
}
}