use crate::{init_clock_freq, tick};
use crate::nano_alloc::TaskNode;
use core::task::{Context, Poll, Waker};
pub struct Executor<'curr, 'next> {
head: Option<&'next mut TaskNode<'curr, 'next>>,
pub freq: u64,
}
impl<'curr, 'next> Executor<'curr, 'next> {
#[inline]
pub fn new() -> Self { Self{ head: None, freq: init_clock_freq() } }
#[inline]
pub fn add(&mut self, node: &'next mut TaskNode<'curr, 'next>) -> &mut Self {
node.interval = self.freq.checked_div(node.interval).unwrap_or(0);
node.next = self.head.take();
self.head = Some(node);
self
}
#[inline(always)]
pub fn run_forever(&mut self) {
let mut cx = Self::init_step();
loop { self.run_step(tick(), &mut cx) }
}
#[inline(always)]
pub fn init_step() -> Context<'curr> { Context::from_waker(&Waker::noop()) }
#[inline(always)]
pub fn run_step(&mut self, time: u64, cx: &mut Context) {
let mut cursor = &mut self.head;
while let Some(node) = cursor {
if time >= node.next_run_time {
match node.future.as_mut().poll(cx) {
Poll::Ready(_) => *cursor = node.next.take(),
Poll::Pending => node.next_run_time = time + node.interval,
}
}
cursor = match { cursor } {
Some(node) => &mut node.next,
None => break,
};
}
}
}