use std::{
collections::BTreeMap,
future::Future,
pin::Pin,
sync::Arc,
task::{Context, Poll, Waker},
time::{Duration, Instant},
};
use super::{Inner, Runtime, lock};
pub struct Sleep {
inner: Arc<Inner>,
deadline: Instant,
id: Option<u64>,
}
impl Sleep {
pub(super) fn new(inner: Arc<Inner>, duration: Duration) -> Self {
Self {
inner,
deadline: Instant::now() + duration,
id: None,
}
}
}
impl Future for Sleep {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
let this = self.get_mut();
if Instant::now() >= this.deadline {
return Poll::Ready(());
}
let mut timers = lock(&this.inner.timers);
let id = match this.id {
Some(id) => id,
None => {
let id = timers.next_id;
timers.next_id += 1;
this.id = Some(id);
id
}
};
timers
.pending
.insert((this.deadline, id), cx.waker().clone());
Poll::Pending
}
}
impl Drop for Sleep {
fn drop(&mut self) {
if let Some(id) = self.id {
lock(&self.inner.timers)
.pending
.remove(&(self.deadline, id));
}
}
}
impl Runtime {
pub(super) fn wake_due_timers(&self) {
let due = {
let mut timers = lock(&self.0.timers);
let later = timers.pending.split_off(&(Instant::now(), u64::MAX));
std::mem::replace(&mut timers.pending, later)
};
for waker in due.into_values() {
waker.wake();
}
}
}
#[derive(Default)]
pub(super) struct Timers {
pub(super) pending: BTreeMap<(Instant, u64), Waker>,
next_id: u64,
}