use crate::forwarder::{Receiver, forwarder};
use crate::{Executor, ExecutorState, Spawner, Task};
use alloc::boxed::Box;
use alloc::rc::Rc;
use core::cell::RefCell;
use core::future::{Future, IntoFuture};
use core::pin::Pin;
impl<'a> Executor<'a> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn wake_count(&self) -> usize {
self.state.borrow().wake_queue.len()
}
pub unsafe fn spawn_pinned(&self, future: Pin<Box<dyn Future<Output = ()> + 'a>>) {
ExecutorState::enqueue(&self.state, future);
}
pub unsafe fn spawn<F, T>(&self, future: F) -> Receiver<T>
where
F: IntoFuture<Output = T> + 'a,
T: 'a,
{
ExecutorState::enqueue_forwarding(&self.state, future)
}
#[must_use]
pub fn spawner(&self) -> Spawner<'a> {
let state = Rc::downgrade(&self.state);
Spawner { state }
}
pub fn step(&self) -> Option<bool> {
let task = self.state.borrow_mut().wake_queue.pop_front()?;
Some(task.poll())
}
pub fn run_until_stalled(&self) -> usize {
let mut completed = 0;
while let Some(is_complete) = self.step() {
if is_complete {
completed += 1;
}
}
completed
}
}
impl<'a> ExecutorState<'a> {
pub(crate) fn enqueue(
this: &Rc<RefCell<Self>>,
future: Pin<Box<dyn Future<Output = ()> + 'a>>,
) {
let task = Task {
executor: Rc::downgrade(this),
future: RefCell::new(Some(future)),
};
this.borrow_mut().wake_queue.push_back(Rc::new(task));
}
pub(crate) fn enqueue_forwarding<F, T>(this: &Rc<RefCell<Self>>, future: F) -> Receiver<T>
where
F: IntoFuture<Output = T> + 'a,
T: 'a,
{
let (sender, receiver) = forwarder();
let task = Task {
executor: Rc::downgrade(this),
future: RefCell::new(Some(Box::pin(async move {
sender.send(future.await).unwrap_or_default()
}))),
};
this.borrow_mut().wake_queue.push_back(Rc::new(task));
receiver
}
}