diff --git a/mission_rust/src/lib.rs b/mission_rust/src/lib.rs index d2ee486..91d83dc 100644 --- a/mission_rust/src/lib.rs +++ b/mission_rust/src/lib.rs @@ -84,21 +84,28 @@ extern "C" fn rust_main() { extern "C" fn task_entry(task_object: *mut cty::c_void) { sifln!("Task Entry"); sifln!("running pointer {:p}", task_object); - let task: &mut PeriodicTask; + let task: &mut dyn TaskIF; unsafe { let pointer = task_object as *mut PeriodicTask; task = &mut *pointer; } sifln!("running cast {:p}", task); - task.execute(); + task.run(); } trait ExecutableObjectIF { fn perform(&mut self); } +trait TaskIF { + fn run(&mut self); + fn get_stack_size(&self) -> cty::size_t; + fn set_handle(&mut self, task_handle: *const cty::c_void); + fn get_handle(&self) -> *const cty::c_void; +} + struct PeriodicTask<'a> { - stack_size: cty::size_t, + stack_size: cty::size_t, //TODO generic type and safety task_handle: *const cty::c_void, period: usize, task_object: &'a mut dyn ExecutableObjectIF, @@ -114,37 +121,51 @@ impl<'a> PeriodicTask<'a> { }; instance } +} - fn execute(&mut self) { +impl<'a> TaskIF for PeriodicTask<'a> { + fn run(&mut self) { sifln!("Task running {}", self.period); loop { self.task_object.perform(); unsafe { - task_delay(self.period as cty::uint32_t); + task_delay(self.period as cty::uint32_t); //TODO type of delay should be generic but safe (cap to max in C) } } } + fn get_stack_size(&self) -> cty::size_t { + self.stack_size + } + fn set_handle(&mut self, task_handle: *const cty::c_void) { + self.task_handle = task_handle; + } + fn get_handle(&self) -> *const cty::c_void { + self.task_handle + } } struct TaskExecutor<'a> { - tasks: &'a mut [PeriodicTask<'a>], + tasks: &'a mut [&'a mut dyn TaskIF], } impl<'a> TaskExecutor<'a> { fn run_tasks(&mut self) { for task in self.tasks.iter_mut() { - // we give away a raw pointer, top be called by an OS task - // while this is generally very broke, we use a reference tied + // we give away a raw pointer, to be called by an OS task + // while this is generally very broken, we use a reference tied // to our own lifetime and destroy the task when we get dropped // this way, the reference is guaranteed to be valid over our // lifetime while the task is deleted at the end of our lifetime - let task_pointer: *const cty::c_void = task as *mut _ as *const cty::c_void; - sifln!("create task {:p}", task_pointer); + let task_pointer: *const cty::c_void = *task as *mut _ as *const cty::c_void; //TODO this does work without the "*" in front of the task -> Why?? + sifln!("create task {:p}", task_pointer); + let handle; unsafe { - task.task_handle = create_task(task_entry, task_pointer, task.stack_size); + handle = create_task(task_entry, task_pointer, task.get_stack_size()); } - if task.task_handle == 0 as *mut cty::c_void { + if handle == 0 as *mut cty::c_void { panic!("could not create Task"); + } else { + task.set_handle(handle); } } } @@ -154,7 +175,7 @@ impl<'a> Drop for TaskExecutor<'a> { fn drop(&mut self) { for task in self.tasks.iter_mut() { unsafe { - delete_task(task.task_handle); + delete_task(task.get_handle()); } } } @@ -320,18 +341,27 @@ fn mission() { }; let mut h2 = Handler { id: 2, - // cycle: 0, - // other_handler: MessageQueueSender::::new(), + // cycle: 0, + // other_handler: MessageQueueSender::::new(), }; // h2.other_handler = h1.command_queue.get_sender(); - let t1: PeriodicTask = PeriodicTask::new(&mut h1, 512, 200); + let mut t1: PeriodicTask = PeriodicTask::new(&mut h1, 512, 200); - let t2: PeriodicTask = PeriodicTask::new(&mut h2, 512, 300); + let mut t2: PeriodicTask = PeriodicTask::new(&mut h2, 512, 300); + sifln!("t1 {:p}", &t1); - let mut task_executor = TaskExecutor{tasks: &mut [t1,t2]}; + let r1: &mut dyn TaskIF = &mut t1; + + sifln!("as dyn {:p}", r1); + + let mut task_executor = TaskExecutor { + tasks: &mut [&mut t1, &mut t2], + }; + + sifln!("{:p}", task_executor.tasks[0]); task_executor.run_tasks(); @@ -339,7 +369,7 @@ fn mission() { unsafe { task_delay(2000); } - sifln!("Mission delay2"); + sifln!("executor dropped"); drop(task_executor); //t2.period = 100; //Invalid h1.id = 2;