use std::{
fmt::Display,
sync::{mpsc::SyncSender, Arc},
task::{Context, Poll, Waker},
};
use crate::task::{manager::TaskManager, Task};
pub type BlockingFn = dyn FnOnce() + Send + 'static;
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct ExecutorId(usize);
impl ExecutorId {
pub fn get(&self) -> usize {
self.0
}
}
pub enum ExecutorTask {
Task(Arc<Task>),
Finished,
}
impl Display for ExecutorTask {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ExecutorTask::Task(_) => write!(f, "ExecutorTask::Task"),
ExecutorTask::Finished => write!(f, "ExecutorTask::Finished"),
}
}
}
#[derive(Debug)]
pub enum Status {
Awaited(Waker),
Happened,
}
pub struct Executor {
ready_queue: std::sync::mpsc::Receiver<ExecutorTask>,
panic_tx: SyncSender<()>,
id: ExecutorId,
}
impl Executor {
pub fn new(
rx: std::sync::mpsc::Receiver<ExecutorTask>,
executor_id: usize,
panic_tx: SyncSender<()>,
) -> Self {
Self {
ready_queue: rx,
panic_tx,
id: ExecutorId(executor_id),
}
}
pub fn run(&self) {
while let Ok(task) = self.ready_queue.recv() {
match task {
ExecutorTask::Finished => return, ExecutorTask::Task(task) => self.forward_task(task), };
let tm = TaskManager::get();
tm.executor_ready(self.id());
}
}
fn forward_task(&self, task: Arc<Task>) {
let mut future = task.future.lock().unwrap();
let waker = Arc::clone(&task).waker();
let mut context = Context::from_waker(&waker);
if let Err(e) = std::panic::catch_unwind(move || {
if let Some(fut) = future.as_mut() {
match fut.as_mut().poll(&mut context) {
Poll::Pending => {
}
Poll::Ready(()) => {
*future = None;
}
}
}
}) {
println!("EXECUTOR PANIC FUNCTION. ERROR: {:?}", e);
self.panic_tx.send(()).unwrap(); }
}
pub fn id(&self) -> ExecutorId {
self.id
}
}