use std::{ error, fmt, future::Future, pin::Pin, sync::{ mpsc::{Receiver, Sender}, Arc, Mutex, }, task::Wake, }; #[derive(Debug)] pub struct Executor { task_receiver: Receiver>, } impl Executor { pub fn run(&self) { while let Ok(task) = self.task_receiver.recv() { task.run(); } } pub fn run_until_stalled(&self) { while let Ok(task) = self.task_receiver.try_recv() { task.run(); } } } #[derive(Clone, Debug)] pub struct Spawner { task_sender: Sender>, } impl Spawner { pub fn spawn(&self, future: impl Future + 'static) -> Result<(), SpawnError> { if self .task_sender .send(Arc::new(Task { inner: Mutex::new(TaskInner { future: Some(Box::pin(future)), task_sender: self.task_sender.clone(), }), })) .is_err() { return Err(SpawnError::shutdown()); } Ok(()) } } #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct SpawnError { _priv: (), } impl SpawnError { pub fn shutdown() -> Self { Self { _priv: () } } } impl error::Error for SpawnError {} impl fmt::Display for SpawnError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "executor is shutdown") } } struct Task { inner: Mutex, } impl Task { fn run(self: Arc) { use {crate::task, std::task::Context}; let future = self.inner.lock().unwrap().future.take(); if let Some(mut future) = future { let waker = task::waker(self.clone()); let mut cx = Context::from_waker(&waker); if future.as_mut().poll(&mut cx).is_pending() { self.inner.lock().unwrap().future = Some(future); } } } } impl Wake for Task { fn wake(self: Arc) { self.inner .lock() .unwrap() .task_sender .send(self.clone()) .unwrap(); } } struct TaskInner { future: Option + 'static>>>, task_sender: Sender>, } pub fn new_executor_and_spawner() -> (Executor, Spawner) { use std::sync::mpsc; let (task_sender, task_receiver) = mpsc::channel(); (Executor { task_receiver }, Spawner { task_sender }) }