task/manager/
lifecycle.rs1use super::*;
4use alloc::boxed::Box;
5use core::{
6 future::{Future, poll_fn},
7 ptr::NonNull,
8 task::Poll,
9 time::Duration,
10};
11use embassy_executor::raw::{TaskPool, task_from_waker};
12use embassy_futures::yield_now;
13use embassy_time::Timer;
14
15impl Manager {
16 async fn create_and_run_task<R: 'static, FunctionType, FutureType>(
20 manager: &'static Manager,
21 parent_task_identifier: TaskIdentifier,
22 name: &str,
23 function: FunctionType,
24 spawner: Option<usize>,
25 ) -> Result<(JoinHandle<R>, TaskIdentifier)>
26 where
27 FunctionType: FnOnce(TaskIdentifier) -> FutureType + 'static,
28 FutureType: Future<Output = R> + 'static,
29 {
30 let identifier = manager
31 .register(parent_task_identifier, name)
32 .await
33 .expect("Failed to get new task identifier");
34
35 let pool = Box::new(TaskPool::<_, 1>::new());
36 let pool = Box::leak(pool);
37
38 let (join_handle_parent, join_handle_child) = JoinHandle::new();
39
40 let task = async move || {
41 let manager = get_instance();
42
43 let internal_identifier = Manager::get_current_internal_identifier().await;
44
45 manager
46 .set_internal_identifier(identifier, internal_identifier)
47 .await
48 .expect("Failed to register task");
49
50 let result = function(identifier).await;
51
52 join_handle_child.signal(result);
53
54 manager
55 .unregister(identifier)
56 .await
57 .expect("Failed to unregister task");
58 };
59
60 let mut inner = manager.0.write().await;
61
62 let spawner = if let Some(spawner) = spawner {
64 if !inner.spawners.contains_key(&spawner) {
65 return Err(Error::InvalidSpawnerIdentifier);
66 }
67 spawner
68 } else {
69 Manager::select_best_spawner(&inner)?
70 };
71
72 inner
73 .tasks
74 .get_mut(&identifier)
75 .expect("Failed to get task metadata")
76 .spawner_identifier = spawner;
77
78 let token = pool.spawn(task);
79
80 inner
81 .spawners
82 .get(&spawner)
83 .expect("Failed to get spawner")
84 .spawn(token)
85 .expect("Failed to spawn task");
86
87 Ok((join_handle_parent, identifier))
88 }
89
90 pub async fn spawn<FunctionType, FutureType, ReturnType>(
92 &'static self,
93
94 parent_task: TaskIdentifier,
95 name: &str,
96 spawner: Option<usize>,
97 function: FunctionType,
98 ) -> Result<(JoinHandle<ReturnType>, TaskIdentifier)>
99 where
100 FunctionType: FnOnce(TaskIdentifier) -> FutureType + 'static,
101 FutureType: Future<Output = ReturnType> + 'static,
102 ReturnType: 'static,
103 {
104 Self::create_and_run_task(self, parent_task, name, function, spawner).await
106 }
107
108 async fn set_internal_identifier(
113 &self,
114 identifier: TaskIdentifier,
115 internal_identifier: usize,
116 ) -> Result<()> {
117 let mut inner = self.0.write().await;
118
119 let metadata = Self::get_task_mutable(&mut inner, identifier)?;
120
121 metadata.internal_identifier = internal_identifier;
122
123 if let Some(old_identifier) = inner.identifiers.insert(internal_identifier, identifier) {
125 inner.identifiers.remove(&internal_identifier);
127 inner
128 .identifiers
129 .insert(internal_identifier, old_identifier);
130 return Err(Error::InvalidTaskIdentifier);
131 }
132
133 Ok(())
134 }
135
136 pub async fn r#yield() {
137 yield_now().await;
138 }
139
140 pub async fn sleep(duration: Duration) {
142 let nano_seconds = duration.as_nanos();
143
144 Timer::after(embassy_time::Duration::from_nanos(nano_seconds as u64)).await
145 }
146
147 pub async fn get_current_internal_identifier() -> usize {
148 poll_fn(|context| {
149 let task_reference = task_from_waker(context.waker());
150
151 let inner: NonNull<u8> = unsafe { core::mem::transmute(task_reference) };
152
153 let identifier = inner.as_ptr() as usize;
154
155 Poll::Ready(identifier)
156 })
157 .await
158 }
159
160 pub async fn get_current_task_identifier(&self) -> TaskIdentifier {
161 let internal_identifier = Self::get_current_internal_identifier().await;
162
163 *self
164 .0
165 .read()
166 .await
167 .identifiers
168 .get(&internal_identifier)
169 .expect("Failed to get task identifier")
170 }
171}