1use std::cell::Cell;
2use std::future::Future;
3use std::pin::Pin;
4use std::rc::Rc;
5use std::task::{Context, Poll};
6
7use crate::runtime;
8use crate::tween::progress;
9
10pub type BoxFuture<T = ()> = Pin<Box<dyn Future<Output = T>>>;
12
13fn poll_scoped<F: Future + ?Sized>(
15 fut: Pin<&mut F>,
16 time: &mut f64,
17 cx: &mut Context<'_>,
18) -> Poll<F::Output> {
19 runtime::with(|rt| {
20 let outer = rt.task_time.replace(*time);
21 let r = fut.poll(cx);
24 *time = rt.task_time.replace(outer);
25 r
26 })
27}
28
29pub fn wait_for(seconds: f64) -> WaitFor {
33 WaitFor {
34 duration: seconds.max(0.0),
35 start: None,
36 }
37}
38
39#[must_use = "futures do nothing unless awaited"]
40pub struct WaitFor {
41 duration: f64,
42 start: Option<f64>,
43}
44
45impl Future for WaitFor {
46 type Output = ();
47
48 fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
49 let start = *self.start.get_or_insert_with(runtime::time);
50 match progress(start, self.duration) {
51 None => Poll::Ready(()),
52 Some(_) => Poll::Pending,
53 }
54 }
55}
56
57pub fn wait_until(name: &str) -> WaitUntil {
60 WaitUntil {
61 name: name.to_owned(),
62 inner: None,
63 }
64}
65
66#[must_use = "futures do nothing unless awaited"]
67pub struct WaitUntil {
68 name: String,
69 inner: Option<WaitFor>,
70}
71
72impl Future for WaitUntil {
73 type Output = ();
74
75 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
76 let this = &mut *self;
77 let inner = this.inner.get_or_insert_with(|| {
78 let target = runtime::marker(&this.name);
79 wait_for(target - runtime::time())
80 });
81 Pin::new(inner).poll(cx)
82 }
83}
84
85pub fn next_frame() -> NextFrame {
87 NextFrame { frame: None }
88}
89
90#[must_use = "futures do nothing unless awaited"]
91pub struct NextFrame {
92 frame: Option<u32>,
93}
94
95impl Future for NextFrame {
96 type Output = ();
97
98 fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
99 let current = runtime::frame();
100 let first = *self.frame.get_or_insert(current);
101 if current > first {
102 runtime::with(|rt| rt.task_time.set(rt.task_time.get().max(rt.now())));
103 Poll::Ready(())
104 } else {
105 Poll::Pending
106 }
107 }
108}
109
110pub struct Branch<F: Future> {
114 fut: Option<Pin<Box<F>>>,
115 out: Option<F::Output>,
116 time: f64,
117}
118
119impl<F: Future> Branch<F> {
120 fn new(fut: F) -> Self {
121 Self {
122 fut: Some(Box::pin(fut)),
123 out: None,
124 time: f64::NAN,
125 }
126 }
127
128 fn poll(&mut self, start: f64, cx: &mut Context<'_>) -> bool {
130 if self.time.is_nan() {
131 self.time = start;
132 }
133 if let Some(fut) = self.fut.as_mut()
134 && let Poll::Ready(v) = poll_scoped(fut.as_mut(), &mut self.time, cx)
135 {
136 self.out = Some(v);
137 self.fut = None;
138 }
139 self.fut.is_none()
140 }
141
142 fn take(&mut self) -> F::Output {
143 self.out.take().expect("branch output taken twice")
144 }
145}
146
147pub fn all<T: IntoAll>(futures: T) -> All<T::Branches> {
153 All {
154 branches: futures.into_branches(),
155 start: None,
156 }
157}
158
159#[must_use = "futures do nothing unless awaited"]
160pub struct All<B> {
162 branches: B,
163 start: Option<f64>,
164}
165
166pub trait IntoAll {
167 type Branches: Branches;
168 fn into_branches(self) -> Self::Branches;
169}
170
171pub trait Branches {
172 type Output;
173 fn poll_all(&mut self, start: f64, cx: &mut Context<'_>) -> Option<f64>;
175 fn take(&mut self) -> Self::Output;
176}
177
178impl<B: Branches + Unpin> Future for All<B> {
179 type Output = B::Output;
180
181 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<B::Output> {
182 let this = &mut *self;
183 let start = *this.start.get_or_insert_with(runtime::time);
184 match this.branches.poll_all(start, cx) {
185 Some(end) => {
186 runtime::with(|rt| rt.task_time.set(end));
187 Poll::Ready(this.branches.take())
188 }
189 None => Poll::Pending,
190 }
191 }
192}
193
194macro_rules! impl_all {
195 ($($F:ident $i:tt),+) => {
196 impl<$($F: Future),+> IntoAll for ($($F,)+) {
197 type Branches = ($(Branch<$F>,)+);
198 fn into_branches(self) -> Self::Branches {
199 ($(Branch::new(self.$i),)+)
200 }
201 }
202
203 impl<$($F: Future),+> Branches for ($(Branch<$F>,)+) {
204 type Output = ($($F::Output,)+);
205
206 fn poll_all(&mut self, start: f64, cx: &mut Context<'_>) -> Option<f64> {
207 let mut done = true;
208 $( done &= self.$i.poll(start, cx); )+
209 done.then(|| {
210 let mut end = start;
211 $( end = end.max(self.$i.time); )+
212 end
213 })
214 }
215
216 fn take(&mut self) -> Self::Output {
217 ($(self.$i.take(),)+)
218 }
219 }
220 };
221}
222
223impl_all!(A 0);
224impl_all!(A 0, B 1);
225impl_all!(A 0, B 1, C 2);
226impl_all!(A 0, B 1, C 2, D 3);
227impl_all!(A 0, B 1, C 2, D 3, E 4);
228impl_all!(A 0, B 1, C 2, D 3, E 4, F 5);
229impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6);
230impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
231impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8);
232impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9);
233impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10);
234impl_all!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11);
235
236pub fn all_vec<T: 'static>(futures: Vec<BoxFuture<T>>) -> All<VecBranches<T>> {
238 All {
239 branches: VecBranches(futures.into_iter().map(Branch::new).collect()),
240 start: None,
241 }
242}
243
244pub struct VecBranches<T>(Vec<Branch<BoxFuture<T>>>);
245
246impl<T> Branches for VecBranches<T> {
247 type Output = Vec<T>;
248
249 fn poll_all(&mut self, start: f64, cx: &mut Context<'_>) -> Option<f64> {
250 let mut done = true;
251 for b in &mut self.0 {
252 done &= b.poll(start, cx);
253 }
254 done.then(|| self.0.iter().fold(start, |end, b| end.max(b.time)))
255 }
256
257 fn take(&mut self) -> Vec<T> {
258 self.0.iter_mut().map(Branch::take).collect()
259 }
260}
261
262pub fn sequence(delay: f64, futures: Vec<BoxFuture>) -> All<VecBranches<()>> {
265 all_vec(
266 futures
267 .into_iter()
268 .enumerate()
269 .map(|(i, f)| -> BoxFuture {
270 let offset = delay * i as f64;
271 Box::pin(async move {
272 wait_for(offset).await;
273 f.await;
274 })
275 })
276 .collect(),
277 )
278}
279
280pub(crate) struct TaskState {
283 pub finished: Cell<bool>,
284 pub cancelled: Cell<bool>,
285}
286
287pub(crate) struct Task {
288 pub fut: BoxFuture,
289 pub time: f64,
290 pub state: Rc<TaskState>,
291}
292
293impl Task {
294 pub fn poll(&mut self, cx: &mut Context<'_>) -> bool {
296 if self.state.cancelled.get() {
297 return true;
298 }
299 if poll_scoped(self.fut.as_mut(), &mut self.time, cx).is_ready() {
300 self.state.finished.set(true);
301 }
302 self.state.finished.get()
303 }
304}
305
306pub fn spawn(fut: impl Future<Output = ()> + 'static) -> JoinHandle {
309 let state = Rc::new(TaskState {
310 finished: Cell::new(false),
311 cancelled: Cell::new(false),
312 });
313 runtime::with(|rt| {
314 rt.spawned.borrow_mut().push(Task {
315 fut: Box::pin(fut),
316 time: rt.task_time.get(),
317 state: state.clone(),
318 });
319 });
320 JoinHandle { state }
321}
322
323pub struct JoinHandle {
325 state: Rc<TaskState>,
326}
327
328impl JoinHandle {
329 pub fn is_finished(&self) -> bool {
331 self.state.finished.get()
332 }
333
334 pub fn cancel(&self) {
336 self.state.cancelled.set(true);
337 }
338}
339
340impl Future for JoinHandle {
341 type Output = ();
342
343 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
344 if self.state.finished.get() || self.state.cancelled.get() {
345 Poll::Ready(())
346 } else {
347 Poll::Pending
348 }
349 }
350}