uefi_async/nano_alloc/control.rs
1
2
3pub mod multiple {
4 pub use futures_concurrency::*;
5}
6
7pub mod single {
8 pub mod join {
9 use core::future::Future;
10 use core::pin::Pin;
11 use core::task::{Context, Poll};
12 use pin_project::pin_project;
13
14 /// Joins multiple futures together, running them concurrently until all complete.
15 ///
16 /// This macro expands to a nested `Join` structure. It does not return any values
17 /// and is intended for tasks that perform side effects (returning `()`).
18 ///
19 /// # Examples
20 /// ```
21 /// join!(task_one(), task_two(), async { do_something().await }).await;
22 /// ```
23 pub use uefi_async_macros::join;
24
25 /// Joins multiple `Result`-returning futures, short-circuiting on the first error.
26 ///
27 /// If any future returns an `Err`, the `try_join!` completes immediately with that error.
28 /// Otherwise, it waits until all tasks complete successfully.
29 ///
30 /// # Examples
31 /// ```
32 /// let result = try_join!(disk_load(), network_fetch()).await;
33 /// if result.is_err() {
34 /// println!("One of the tasks failed!");
35 /// }
36 /// ```
37 pub use uefi_async_macros::try_join;
38
39 /// Joins multiple futures and collects their results into a flattened tuple.
40 ///
41 /// Unlike `join!`, `join_all!` preserves the output of each future. The macro
42 /// automatically flattens the internal recursive structure so you receive a
43 /// standard tuple of results.
44 ///
45 /// # Examples
46 /// ```
47 /// let (mesh, texture) = join_all!(load_mesh(), load_texture()).await;
48 /// render_engine.draw(mesh, texture);
49 /// ```
50 pub use uefi_async_macros::join_all;
51
52 /// A Future that polls two sub-futures to completion.
53 ///
54 /// This is the primitive building block for the `join!` macro. It stores the completion
55 /// state of two futures and returns `Ready` only when both are done.
56 #[pin_project]
57 pub struct Join<H, T> {
58 #[pin] pub head: H,
59 #[pin] pub tail: T,
60 pub head_done: bool,
61 pub tail_done: bool,
62 }
63
64 impl<H: Future<Output = ()>, T: Future<Output = ()>> Future for Join<H, T> {
65 type Output = ();
66
67 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
68 let this = self.project();
69
70 if !*this.head_done { *this.head_done = this.head.poll(cx).is_ready() }
71 if !*this.tail_done { *this.tail_done = this.tail.poll(cx).is_ready() }
72 if *this.head_done && *this.tail_done { Poll::Ready(()) } else { Poll::Pending }
73 }
74 }
75
76 /// A Future that polls two `Result`-returning sub-futures with short-circuiting logic.
77 ///
78 /// If either `head` or `tail` returns `Err`, this Future resolves to that `Err` immediately.
79 /// It is the foundation for the `try_join!` macro.
80 #[pin_project]
81 pub struct TryJoin<H, T> {
82 #[pin] pub head: H,
83 #[pin] pub tail: T,
84 pub head_done: bool,
85 pub tail_done: bool,
86 }
87
88 impl<E, H: Future<Output = Result<(),E>>, T: Future<Output = Result<(),E>>> Future for TryJoin<H, T> {
89 type Output = Result<(), E>;
90
91 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
92 let this = self.project();
93
94 // 1. 轮询第一个任务 (Head)
95 if !*this.head_done {
96 match this.head.poll(cx) {
97 Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), // 遇到错误立刻中断
98 Poll::Ready(Ok(_)) => *this.head_done = true, // 标记成功
99 Poll::Pending => {}
100 }
101 }
102
103 // 2. 轮询第二个任务 (Tail)
104 if !*this.tail_done {
105 match this.tail.poll(cx) {
106 Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), // 遇到错误立刻中断
107 Poll::Ready(Ok(_)) => *this.tail_done = true, // 标记成功
108 Poll::Pending => {}
109 }
110 }
111
112 // 3. 只有当两者都成功时,才返回 Ok
113 if *this.head_done && *this.tail_done { Poll::Ready(Ok(())) } else { Poll::Pending }
114 }
115 }
116
117 /// A Future that polls two sub-futures and stores their outputs.
118 ///
119 /// Once both futures resolve, the outputs are returned as a tuple.
120 #[pin_project]
121 pub struct JoinAll<H: Future, T: Future> {
122 #[pin] pub head: H,
123 #[pin] pub tail: T,
124 pub head_res: Option<H::Output>,
125 pub tail_res: Option<T::Output>,
126 }
127
128 impl<H: Future, T: Future> JoinAll<H, T> {
129 pub fn new(head: H, tail: T) -> Self { Self { head, tail, head_res: None, tail_res: None } }
130 }
131
132 impl<H: Future, T: Future> Future for JoinAll<H, T> {
133 type Output = (H::Output, T::Output);
134 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
135 let this = self.project();
136
137 if this.head_res.is_none() {
138 if let Poll::Ready(out) = this.head.poll(cx) {
139 *this.head_res = Some(out);
140 }
141 }
142 if this.tail_res.is_none() {
143 if let Poll::Ready(out) = this.tail.poll(cx) {
144 *this.tail_res = Some(out);
145 }
146 }
147
148 if this.head_res.is_some() && this.tail_res.is_some() {
149 let h = unsafe { this.head_res.take().unwrap_unchecked() };
150 let t = unsafe { this.tail_res.take().unwrap_unchecked() };
151 Poll::Ready((h, t))
152 } else {
153 Poll::Pending
154 }
155 }
156 }
157 }
158}
159