mod waker;
use crate::{err, error::Error, runtime};
use core::{future::Future, pin::Pin, task::Context};
pub struct Executor<'a, T, const LEN: usize = 32>
where
T: ?Sized,
{
futures: [Option<Pin<&'a mut T>>; LEN],
len: usize,
}
impl<'a, T, const LEN: usize> Executor<'a, T, LEN>
where
T: Future<Output = ()> + ?Sized,
{
const INIT: Option<Pin<&'a mut T>> = None;
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self { futures: [Self::INIT; LEN], len: 0 }
}
pub fn register(&mut self, future: Pin<&'a mut T>) -> Result<&mut Self, Error> {
let Some(slot) = self.futures.get_mut(self.len) else {
return Err(err!("Executor has not enough space to register more futures"));
};
*slot = Some(future);
self.len += 1;
Ok(self)
}
pub fn run(&mut self) {
let waker = waker::new();
let mut context = Context::from_waker(&waker);
let mut remaining = self.len;
while remaining > 0 {
'poll_loop: for index in 0..self.len {
let Some(future) = &mut self.futures[index] else {
continue 'poll_loop;
};
if future.as_mut().poll(&mut context).is_ready() {
self.futures[index] = None;
remaining -= 1;
}
}
unsafe { runtime::_runtime_waitforevent_TBFzxdKN() };
}
}
}
#[macro_export]
macro_rules! run {
($($futures:expr),+) => {{
let execute = || -> core::result::Result<(), $crate::error::Error> {
let mut executor: $crate::executor::Executor<'_, dyn core::future::Future<Output = ()>> =
$crate::executor::Executor::new();
$(
let future = core::pin::pin!($futures);
executor.register(future as core::pin::Pin<&mut dyn core::future::Future<Output = ()>>)?;
)*
executor.run();
Ok(())
};
execute()
}};
}