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