freertos_rust/patterns/
compute_task.rs1use crate::prelude::v1::*;
2use crate::base::*;
3use crate::task::*;
4use crate::mutex::*;
5use crate::queue::*;
6use crate::units::*;
7
8pub trait ComputeTaskBuilder {
9 fn compute<F, R>(&self, func: F) -> Result<ComputeTask<R>, FreeRtosError>
10 where F: FnOnce() -> R,
11 F: Send + 'static,
12 R: Sync + Send + 'static;
13}
14
15impl ComputeTaskBuilder for TaskBuilder {
16 #[cfg(target_os="none")]
17 fn compute<F, R>(&self, func: F) -> Result<ComputeTask<R>, FreeRtosError>
19 where F: FnOnce() -> R,
20 F: Send + 'static,
21 R: Sync + Send + 'static
22 {
23
24 let (task, result, status) = {
25 let result = Arc::new(Mutex::new(None)?);
26 let status = Arc::new(Queue::new(1)?);
27
28 let task_result = result.clone();
29 let task_status = status.clone();
30 let task = self.start(move || {
31 {
32 let mut lock = task_result.lock(Duration::infinite()).unwrap();
33 let r = func();
34 *lock = Some(r);
35 }
36 drop(task_result);
38 task_status.send(ComputeTaskStatus::Finished, Duration::infinite()).unwrap();
39 })?;
40
41 (task, result, status)
42 };
43
44 Ok(ComputeTask {
45 task: task,
46 result: result,
47 status: status,
48 finished: false,
49 })
50 }
51
52 #[cfg(not(target_os="none"))]
53 fn compute<F, R>(&self, func: F) -> Result<ComputeTask<R>, FreeRtosError>
54 where F: FnOnce() -> R,
55 F: Send + 'static,
56 R: Sync + Send + 'static
57 {
58
59 let r = func();
60
61 Ok(ComputeTask {
62 task: Task::new().start(|| {}).unwrap(),
63 result: Arc::new(Mutex::new(Some(r)).unwrap()),
64 status: Arc::new(Queue::new(1).unwrap()),
65 finished: false,
66 })
67 }
68}
69
70pub struct ComputeTask<R> {
88 task: Task,
89 result: Arc<Mutex<Option<R>>>,
90 status: Arc<Queue<ComputeTaskStatus>>,
91 finished: bool,
92}
93
94#[allow(dead_code)]
95#[derive(Debug, Copy, Clone)]
96enum ComputeTaskStatus {
97 Finished,
98}
99
100use core::fmt::Debug;
101
102impl<R: Debug> ComputeTask<R> {
103 pub fn get_task(&self) -> &Task {
105 &self.task
106 }
107
108 pub fn wait_for_result<D: DurationTicks>(&mut self, max_wait: D) -> Result<(), FreeRtosError> {
110 if self.finished == true {
111 Ok(())
112 } else {
113 match self.status.receive(max_wait) {
114 Ok(ComputeTaskStatus::Finished) => {
115 self.finished = true;
116 Ok(())
117 }
118 Err(e) => Err(e),
119 }
120 }
121 }
122
123 pub fn into_result<D: DurationTicks>(mut self, max_wait: D) -> Result<R, FreeRtosError> {
125 self.wait_for_result(max_wait)?;
126
127 if self.finished != true {
128 panic!("ComputeTask should be finished!");
129 }
130
131 let m = Arc::try_unwrap(self.result)
132 .expect("ComputeTask: Arc should have only one reference left!");
133 let option_r = m.into_inner();
134 let r = option_r.expect("ComputeTask: Result should be a Some(R)!");
135
136 Ok(r)
137 }
138}