use bus::BusReader; use std::error::Error; use std::sync::mpsc::TryRecvError; use std::thread; use std::thread::JoinHandle; use std::time::Duration; pub enum OpResult { Ok, TerminationRequested, } pub enum ExecutionType { Infinite, Cycles(u32), OneShot, } pub trait Executable: Send { type Error; fn exec_type(&self) -> ExecutionType; fn task_name(&self) -> &'static str; fn periodic_op(&mut self, op_code: i32) -> Result; } pub fn executable_scheduler< T: Executable + Send + 'static + ?Sized, E: Error + Send + 'static, >( mut executable_vec: Vec>, task_freq: Option, op_code: i32, mut termination: BusReader<()>, ) -> JoinHandle> { let mut cycle_counts = vec![0; executable_vec.len()]; let mut removal_flags = vec![false; executable_vec.len()]; thread::spawn(move || loop { match termination.try_recv() { Ok(_) | Err(TryRecvError::Disconnected) => { removal_flags.iter_mut().for_each(|x| *x = true); } Err(TryRecvError::Empty) => (), } for (idx, executable) in executable_vec.iter_mut().enumerate() { match executable.exec_type() { ExecutionType::OneShot => { executable.periodic_op(op_code)?; removal_flags[idx] = true; } ExecutionType::Infinite => { executable.periodic_op(op_code)?; } ExecutionType::Cycles(cycles) => { executable.periodic_op(op_code)?; cycle_counts[idx] += 1; if cycle_counts[idx] == cycles { removal_flags[idx] = true; } } } } let mut removal_iter = removal_flags.iter(); executable_vec.retain(|_| !*removal_iter.next().unwrap()); removal_iter = removal_flags.iter(); cycle_counts.retain(|_| !*removal_iter.next().unwrap()); removal_flags.retain(|&i| !i); if executable_vec.is_empty() { return Ok(OpResult::Ok); } let freq = task_freq.unwrap_or_else(|| panic!("No task frequency specified")); thread::sleep(freq); }) }