use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
#[derive(Clone, Copy, Debug)]
pub struct Duration {
micros: u64,
}
impl Duration {
pub const fn from_micros(micros: u64) -> Self {
Self { micros }
}
pub const fn from_millis(ms: u64) -> Self {
Self { micros: ms * 1000 }
}
pub const fn as_micros(&self) -> u64 {
self.micros
}
pub const fn as_millis(&self) -> u64 {
self.micros / 1000
}
}
pub struct Sleep<const MICROS: u64> {
deadline: u64,
slot: Option<crate::timer::TimerHandle>,
}
impl<const MICROS: u64> Sleep<MICROS> {
pub const fn new() -> Self {
Self {
deadline: 0,
slot: None,
}
}
}
impl<const MICROS: u64> Default for Sleep<MICROS> {
fn default() -> Self {
Self::new()
}
}
impl<const MICROS: u64> Drop for Sleep<MICROS> {
fn drop(&mut self) {
if let Some(handle) = self.slot.take() {
crate::timer::cancel_deadline(handle);
}
}
}
impl<const MICROS: u64> Future for Sleep<MICROS> {
type Output = ();
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
let this = unsafe { self.get_unchecked_mut() };
let now = crate::port::board::now_us();
if this.deadline == 0 {
let deadline = now.wrapping_add(MICROS).max(1); this.deadline = deadline;
let id = crate::executor::current_task()
.expect("Sleep::poll() called outside of a task context");
let handle = crate::timer::register_deadline(deadline, id).unwrap_or_else(|_| {
panic!(
"rivet: Sleep timer queue full ({} concurrent sleeps supported)",
crate::timer::MAX_TIMERS
)
});
this.slot = Some(handle);
if now >= deadline {
return Poll::Ready(());
}
return Poll::Pending;
}
if now >= this.deadline {
this.slot = None;
Poll::Ready(())
} else {
Poll::Pending
}
}
}