allow passing in task vectors now

This commit is contained in:
Robin Müller 2022-05-26 17:51:10 +02:00
parent 529d2ff67d
commit e4b5df8287
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
2 changed files with 80 additions and 35 deletions

View File

@ -1,5 +1,3 @@
use std::time::Duration;
pub enum OpResult { pub enum OpResult {
Ok, Ok,
} }
@ -13,15 +11,13 @@ pub enum ExecutionType {
pub trait Executable { pub trait Executable {
type Error; type Error;
const EXEC_TYPE: ExecutionType; const EXEC_TYPE: ExecutionType;
const TASK_FREQ: Option<Duration>;
const TASK_NAME: &'static str; const TASK_NAME: &'static str;
fn periodic_op(&mut self, op_code: u32) -> Result<OpResult, Self::Error>; fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, Self::Error>;
} }
trait ExecutableWithAssociatedFuncs { trait ExecutableWithAssociatedFuncs {
type Error; type Error;
fn exec_type(&self) -> ExecutionType; fn exec_type(&self) -> ExecutionType;
fn task_freq(&self) -> Option<Duration>;
fn task_name(&self) -> &'static str; fn task_name(&self) -> &'static str;
fn periodic_op(&mut self) -> Result<OpResult, Self::Error>; fn periodic_op(&mut self) -> Result<OpResult, Self::Error>;
} }

View File

@ -5,7 +5,9 @@ use std::thread;
use std::thread::JoinHandle; use std::thread::JoinHandle;
use std::time::Duration; use std::time::Duration;
struct ExampleTask {} struct OneShotTask {}
struct FixedCyclesTask {}
struct PeriodicTask {}
#[derive(Debug)] #[derive(Debug)]
struct ExampleError { struct ExampleError {
@ -32,28 +34,63 @@ impl Error for ExampleError {
} }
} }
impl Executable for ExampleTask { impl Executable for OneShotTask {
type Error = ExampleError; type Error = ExampleError;
const EXEC_TYPE: ExecutionType = ExecutionType::OneShot; const EXEC_TYPE: ExecutionType = ExecutionType::OneShot;
const TASK_FREQ: Option<Duration> = Some(Duration::from_millis(500)); const TASK_NAME: &'static str = "One Shot Test Task";
const TASK_NAME: &'static str = "Test Task";
fn periodic_op(&mut self, op_code: u32) -> Result<OpResult, ExampleError> { fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, ExampleError> {
if op_code == 0 { if op_code >= 0 {
println!("Periodic Operation OK!"); println!("One-shot operation with operation code {op_code} OK!");
Ok(OpResult::Ok) Ok(OpResult::Ok)
} else { } 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<OpResult, ExampleError> {
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<OpResult, ExampleError> {
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")) Err(ExampleError::new("Example Task Failure"))
} }
} }
} }
fn main() { fn main() {
let exec_task = ExampleTask {}; let exec_task = OneShotTask {};
let jhandle = test_thread(exec_task, 0); let mut task_vec = Vec::new();
let exec_task2 = ExampleTask {}; task_vec.push(exec_task);
let jhandle2 = test_thread(exec_task2, 1); 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 jhandle
.join() .join()
.expect("Joining thread failed") .expect("Joining thread failed")
@ -65,26 +102,38 @@ fn main() {
} }
fn test_thread<T: Executable<Error = E> + Send + 'static, E: Error + Send + 'static>( fn test_thread<T: Executable<Error = E> + Send + 'static, E: Error + Send + 'static>(
mut executable: T, mut executable_vec: Vec<T>,
op_code: u32, task_freq: Option<Duration>,
op_code: i32,
) -> JoinHandle<Result<OpResult, E>> { ) -> JoinHandle<Result<OpResult, E>> {
thread::spawn(move || match T::EXEC_TYPE { let mut cycle_counts = vec![0; executable_vec.len()];
ExecutionType::OneShot => executable.periodic_op(op_code), let mut removal_flags = vec![false; executable_vec.len()];
ExecutionType::Infinite => loop { thread::spawn(move || loop {
executable.periodic_op(op_code)?; for (idx, executable) in executable_vec.iter_mut().enumerate() {
let freq = T::TASK_FREQ match T::EXEC_TYPE {
.unwrap_or_else(|| panic!("No task frequency specified for task {}", T::TASK_NAME)); ExecutionType::OneShot => {
thread::sleep(freq) executable.periodic_op(op_code)?;
}, removal_flags[idx] = true;
ExecutionType::Cycles(cycles) => { }
for _i in 0..cycles - 1 { ExecutionType::Infinite => {
executable.periodic_op(op_code)?; executable.periodic_op(op_code)?;
let freq = T::TASK_FREQ.unwrap_or_else(|| { }
panic!("No task frequency specified for task {}", T::TASK_NAME) ExecutionType::Cycles(cycles) => {
}); executable.periodic_op(op_code)?;
thread::sleep(freq) 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);
}) })
} }