use std::{
fmt::Display,
sync::{mpsc::SyncSender, Arc},
task::{Context, Waker},
};
use crate::task::{manager::TaskManager, Task};
#[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() {
let task = match task {
ExecutorTask::Finished => return, ExecutorTask::Task(task) => 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 || future.as_mut().poll(&mut context)) {
println!("EXECUTOR PANIC FUNCTION. ERROR: {:?}", e);
self.panic_tx.send(()).unwrap(); }
let tm = TaskManager::get();
tm.executor_ready(self.id());
}
}
pub fn id(&self) -> ExecutorId {
self.id
}
}