From e4b5df8287be5e16ac052d38bdd87a84e697da6e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 26 May 2022 17:51:10 +0200 Subject: [PATCH] allow passing in task vectors now --- src/core/executable.rs | 6 +-- src/main.rs | 109 +++++++++++++++++++++++++++++------------ 2 files changed, 80 insertions(+), 35 deletions(-) diff --git a/src/core/executable.rs b/src/core/executable.rs index 527e5ee..eaa6dc0 100644 --- a/src/core/executable.rs +++ b/src/core/executable.rs @@ -1,5 +1,3 @@ -use std::time::Duration; - pub enum OpResult { Ok, } @@ -13,15 +11,13 @@ pub enum ExecutionType { pub trait Executable { type Error; const EXEC_TYPE: ExecutionType; - const TASK_FREQ: Option; const TASK_NAME: &'static str; - fn periodic_op(&mut self, op_code: u32) -> Result; + fn periodic_op(&mut self, op_code: i32) -> Result; } trait ExecutableWithAssociatedFuncs { type Error; fn exec_type(&self) -> ExecutionType; - fn task_freq(&self) -> Option; fn task_name(&self) -> &'static str; fn periodic_op(&mut self) -> Result; } diff --git a/src/main.rs b/src/main.rs index d2bb3d6..234c095 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,9 @@ use std::thread; use std::thread::JoinHandle; use std::time::Duration; -struct ExampleTask {} +struct OneShotTask {} +struct FixedCyclesTask {} +struct PeriodicTask {} #[derive(Debug)] struct ExampleError { @@ -32,28 +34,63 @@ impl Error for ExampleError { } } -impl Executable for ExampleTask { +impl Executable for OneShotTask { type Error = ExampleError; const EXEC_TYPE: ExecutionType = ExecutionType::OneShot; - const TASK_FREQ: Option = Some(Duration::from_millis(500)); - const TASK_NAME: &'static str = "Test Task"; + const TASK_NAME: &'static str = "One Shot Test Task"; - fn periodic_op(&mut self, op_code: u32) -> Result { - if op_code == 0 { - println!("Periodic Operation OK!"); + fn periodic_op(&mut self, op_code: i32) -> Result { + if op_code >= 0 { + println!("One-shot operation with operation code {op_code} OK!"); Ok(OpResult::Ok) } else { - println!("Periodic Operation Fail!"); + println!("One-shot operation failure by passing op code {op_code}!"); + Err(ExampleError::new("Example Task Failure")) + } + } +} + +impl Executable for FixedCyclesTask { + type Error = ExampleError; + const EXEC_TYPE: ExecutionType = ExecutionType::Cycles(5); + const TASK_NAME: &'static str = "Fixed Cycles Task"; + + fn periodic_op(&mut self, op_code: i32) -> Result { + if op_code >= 0 { + println!("Fixed-cycle operation with operation code {op_code} OK!"); + Ok(OpResult::Ok) + } else { + println!("Fixed-cycle operation failure by passing op code {op_code}!"); + Err(ExampleError::new("Example Task Failure")) + } + } +} + +impl Executable for PeriodicTask { + type Error = ExampleError; + const EXEC_TYPE: ExecutionType = ExecutionType::Cycles(5); + const TASK_NAME: &'static str = "Fixed Cycles Task"; + + fn periodic_op(&mut self, op_code: i32) -> Result { + if op_code >= 0 { + println!("Periodic operation with operation code {op_code} OK!"); + Ok(OpResult::Ok) + } else { + println!("Periodic operation failure by passing op code {op_code}!"); Err(ExampleError::new("Example Task Failure")) } } } fn main() { - let exec_task = ExampleTask {}; - let jhandle = test_thread(exec_task, 0); - let exec_task2 = ExampleTask {}; - let jhandle2 = test_thread(exec_task2, 1); + let exec_task = OneShotTask {}; + let mut task_vec = Vec::new(); + task_vec.push(exec_task); + let jhandle = test_thread(task_vec, Some(Duration::from_millis(500)), 0); + let exec_task2 = FixedCyclesTask {}; + let mut task_vec2 = Vec::new(); + task_vec2.push(exec_task2); + let jhandle2 = test_thread(task_vec2, Some(Duration::from_millis(1000)), 1); jhandle .join() .expect("Joining thread failed") @@ -65,26 +102,38 @@ fn main() { } fn test_thread + Send + 'static, E: Error + Send + 'static>( - mut executable: T, - op_code: u32, + mut executable_vec: Vec, + task_freq: Option, + op_code: i32, ) -> JoinHandle> { - thread::spawn(move || match T::EXEC_TYPE { - ExecutionType::OneShot => executable.periodic_op(op_code), - ExecutionType::Infinite => loop { - executable.periodic_op(op_code)?; - let freq = T::TASK_FREQ - .unwrap_or_else(|| panic!("No task frequency specified for task {}", T::TASK_NAME)); - thread::sleep(freq) - }, - ExecutionType::Cycles(cycles) => { - for _i in 0..cycles - 1 { - executable.periodic_op(op_code)?; - let freq = T::TASK_FREQ.unwrap_or_else(|| { - panic!("No task frequency specified for task {}", T::TASK_NAME) - }); - thread::sleep(freq) + let mut cycle_counts = vec![0; executable_vec.len()]; + let mut removal_flags = vec![false; executable_vec.len()]; + thread::spawn(move || loop { + for (idx, executable) in executable_vec.iter_mut().enumerate() { + match T::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; + } + } } - Ok(OpResult::Ok) } + executable_vec.retain(|_| !*removal_flags.iter().next().unwrap()); + removal_flags.retain(|&i| i == false); + if executable_vec.is_empty() { + return Ok(OpResult::Ok); + } + let freq = task_freq + .unwrap_or_else(|| panic!("No task frequency specified for task {}", T::TASK_NAME)); + thread::sleep(freq); }) }