This commit is contained in:
Robin Müller 2022-05-26 18:53:07 +02:00
parent e4b5df8287
commit be2a4ac3a2
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
2 changed files with 56 additions and 26 deletions

View File

@ -8,16 +8,16 @@ pub enum ExecutionType {
OneShot, OneShot,
} }
pub trait Executable { pub trait Executable: Send {
type Error; type Error;
const EXEC_TYPE: ExecutionType; //const EXEC_TYPE: ExecutionType;
const TASK_NAME: &'static str; //const TASK_NAME: &'static str;
fn exec_type(&self) -> ExecutionType;// {
// return Self::EXEC_TYPE;
//}
fn task_name(&self) -> &'static str;//{
// return Self::TASK_NAME;
//}
fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, Self::Error>; fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, Self::Error>;
} }
trait ExecutableWithAssociatedFuncs {
type Error;
fn exec_type(&self) -> ExecutionType;
fn task_name(&self) -> &'static str;
fn periodic_op(&mut self) -> Result<OpResult, Self::Error>;
}

View File

@ -36,8 +36,14 @@ impl Error for ExampleError {
impl Executable for OneShotTask { impl Executable for OneShotTask {
type Error = ExampleError; type Error = ExampleError;
const EXEC_TYPE: ExecutionType = ExecutionType::OneShot;
const TASK_NAME: &'static str = "One Shot Test Task"; fn exec_type(&self) -> ExecutionType {
ExecutionType::OneShot
}
fn task_name(&self) -> &'static str {
"One Shot Task"
}
fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, ExampleError> { fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, ExampleError> {
if op_code >= 0 { if op_code >= 0 {
@ -52,8 +58,14 @@ impl Executable for OneShotTask {
impl Executable for FixedCyclesTask { impl Executable for FixedCyclesTask {
type Error = ExampleError; type Error = ExampleError;
const EXEC_TYPE: ExecutionType = ExecutionType::Cycles(5);
const TASK_NAME: &'static str = "Fixed Cycles Task"; fn exec_type(&self) -> ExecutionType {
ExecutionType::Cycles(5)
}
fn task_name(&self) -> &'static str {
"Fixed Cycles Task"
}
fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, ExampleError> { fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, ExampleError> {
if op_code >= 0 { if op_code >= 0 {
@ -68,8 +80,14 @@ impl Executable for FixedCyclesTask {
impl Executable for PeriodicTask { impl Executable for PeriodicTask {
type Error = ExampleError; type Error = ExampleError;
const EXEC_TYPE: ExecutionType = ExecutionType::Cycles(5);
const TASK_NAME: &'static str = "Fixed Cycles Task"; fn exec_type(&self) -> ExecutionType {
ExecutionType::Infinite
}
fn task_name(&self) -> &'static str {
"Periodic Task"
}
fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, ExampleError> { fn periodic_op(&mut self, op_code: i32) -> Result<OpResult, ExampleError> {
if op_code >= 0 { if op_code >= 0 {
@ -82,15 +100,14 @@ impl Executable for PeriodicTask {
} }
} }
fn main() { fn test0() {
let exec_task = OneShotTask {}; let exec_task = OneShotTask {};
let mut task_vec = Vec::new(); let task_vec = vec![Box::new(exec_task)];
task_vec.push(exec_task);
let jhandle = test_thread(task_vec, Some(Duration::from_millis(500)), 0); let jhandle = test_thread(task_vec, Some(Duration::from_millis(500)), 0);
let exec_task2 = FixedCyclesTask {}; let exec_task2 = FixedCyclesTask {};
let mut task_vec2 = Vec::new(); let task_vec2 = vec![Box::new(exec_task2)];
task_vec2.push(exec_task2);
let jhandle2 = test_thread(task_vec2, Some(Duration::from_millis(1000)), 1); let jhandle2 = test_thread(task_vec2, Some(Duration::from_millis(1000)), 1);
jhandle jhandle
.join() .join()
.expect("Joining thread failed") .expect("Joining thread failed")
@ -100,9 +117,22 @@ fn main() {
.expect("Joining thread 2 failed") .expect("Joining thread 2 failed")
.expect("Task 2 failed"); .expect("Task 2 failed");
} }
fn main() {
fn test_thread<T: Executable<Error = E> + Send + 'static, E: Error + Send + 'static>(
mut executable_vec: Vec<T>, thread::sleep(Duration::from_millis(1000));
let one_shot_in_vec = OneShotTask {};
let cycles_in_vec = FixedCyclesTask {};
let test_vec: Vec<Box<dyn Executable<Error=ExampleError>>> = vec![Box::new(one_shot_in_vec), Box::new(cycles_in_vec)];
let jhandle3 = test_thread(test_vec, Some(Duration::from_millis(500)), 3);
jhandle3
.join()
.expect("Joining thread 3 failed")
.expect("Task 3 failed");
}
fn test_thread<T: Executable<Error = E> + Send + 'static + ?Sized, E: Error + Send + 'static>(
mut executable_vec: Vec<Box<T>>,
task_freq: Option<Duration>, task_freq: Option<Duration>,
op_code: i32, op_code: i32,
) -> JoinHandle<Result<OpResult, E>> { ) -> JoinHandle<Result<OpResult, E>> {
@ -110,7 +140,7 @@ fn test_thread<T: Executable<Error = E> + Send + 'static, E: Error + Send + 'sta
let mut removal_flags = vec![false; executable_vec.len()]; let mut removal_flags = vec![false; executable_vec.len()];
thread::spawn(move || loop { thread::spawn(move || loop {
for (idx, executable) in executable_vec.iter_mut().enumerate() { for (idx, executable) in executable_vec.iter_mut().enumerate() {
match T::EXEC_TYPE { match executable.exec_type() {
ExecutionType::OneShot => { ExecutionType::OneShot => {
executable.periodic_op(op_code)?; executable.periodic_op(op_code)?;
removal_flags[idx] = true; removal_flags[idx] = true;
@ -128,12 +158,12 @@ fn test_thread<T: Executable<Error = E> + Send + 'static, E: Error + Send + 'sta
} }
} }
executable_vec.retain(|_| !*removal_flags.iter().next().unwrap()); executable_vec.retain(|_| !*removal_flags.iter().next().unwrap());
removal_flags.retain(|&i| i == false); removal_flags.retain(|&i| !i);
if executable_vec.is_empty() { if executable_vec.is_empty() {
return Ok(OpResult::Ok); return Ok(OpResult::Ok);
} }
let freq = task_freq let freq = task_freq
.unwrap_or_else(|| panic!("No task frequency specified for task {}", T::TASK_NAME)); .unwrap_or_else(|| panic!("No task frequency specified"));
thread::sleep(freq); thread::sleep(freq);
}) })
} }