leodos_libcfs/runtime/
scope.rs1use core::future::Future;
4use core::pin::Pin;
5use core::task::Context;
6use core::task::Poll;
7
8use heapless::Vec;
9
10use crate::error::CfsError;
11use crate::runtime::task::Task;
12
13#[must_use]
15pub struct Scope<'a, const MAX_TASK_SIZE: usize = 512, const MAX_TASKS: usize = 8> {
16 tasks: Vec<Task<'a, MAX_TASK_SIZE>, MAX_TASKS>,
17}
18
19impl<'a, const MAX_TASK_SIZE: usize, const MAX_TASKS: usize> Scope<'a, MAX_TASK_SIZE, MAX_TASKS> {
20 pub fn new() -> Self {
22 Self { tasks: Vec::new() }
23 }
24
25 pub fn spawn<F>(&mut self, future: F) -> Result<(), CfsError>
27 where
28 F: Future<Output = Result<(), CfsError>> + 'a,
29 {
30 self.tasks
31 .push(Task::new(future))
32 .map_err(|_| CfsError::TaskPoolFull)
33 }
34}
35
36impl<'a, const MAX_TASK_SIZE: usize, const MAX_TASKS: usize> Future
38 for Scope<'a, MAX_TASK_SIZE, MAX_TASKS>
39{
40 type Output = Result<(), CfsError>;
41
42 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
43 let mut all_done = true;
44
45 for task in self.tasks.iter_mut() {
46 if !task.is_done() {
47 match task.poll(cx) {
48 Poll::Ready(Ok(())) => {
49 task.cleanup();
50 }
51 Poll::Ready(Err(e)) => {
52 return Poll::Ready(Err(e));
53 }
54 Poll::Pending => {
55 all_done = false;
56 }
57 }
58 }
59 }
60
61 if all_done && !self.tasks.is_empty() {
62 Poll::Ready(Ok(()))
63 } else {
64 Poll::Pending
65 }
66 }
67}