Skip to main content

zng_task/
lib.rs

1#![doc(html_favicon_url = "https://zng-ui.github.io/res/zng-logo-icon.png")]
2#![doc(html_logo_url = "https://zng-ui.github.io/res/zng-logo.png")]
3//!
4//! Parallel async tasks and async task runners.
5//!
6//! # Crate
7//!
8#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
9#![warn(unused_extern_crates)]
10#![warn(missing_docs)]
11
12use std::{
13    any::Any,
14    fmt,
15    hash::Hash,
16    mem, panic,
17    pin::Pin,
18    sync::{
19        Arc,
20        atomic::{AtomicBool, Ordering},
21    },
22    task::Poll,
23};
24
25use zng_app_context::{LocalContext, app_local};
26use zng_time::Deadline;
27use zng_var::{ResponseVar, VarValue, response_done_var, response_var};
28
29#[cfg(test)]
30mod tests;
31
32mod reexports;
33pub use reexports::*;
34
35use crate::parking_lot::Mutex;
36
37pub mod channel;
38pub mod fs;
39pub mod io;
40
41mod ui;
42pub use ui::*;
43
44pub mod http;
45
46pub mod process;
47
48mod rayon_ctx;
49
50mod progress;
51pub use progress::*;
52
53/// Spawn a parallel async task, this function is not blocking and the `task` starts executing immediately.
54///
55/// # Parallel
56///
57/// The task runs in the primary [`rayon`] thread-pool, every [`poll`](Future::poll) happens inside a call to `rayon::spawn`.
58///
59/// You can use parallel iterators, `join` or any of rayon's utilities inside `task` to make it multi-threaded,
60/// otherwise it will run in a single thread at a time, still not blocking the UI.
61///
62/// The [`rayon`] crate is re-exported in `task::rayon` for convenience and compatibility.
63///
64/// # Async
65///
66/// The `task` is also a future so you can `.await`, after each `.await` the task continues executing in whatever `rayon` thread
67/// is free, so the `task` should either be doing CPU intensive work or awaiting, blocking IO operations
68/// block the thread from being used by other tasks reducing overall performance. You can use [`wait`] for IO
69/// or blocking operations and for networking you can use any of the async crates, as long as they start their own *event reactor*.
70///
71/// The `task` lives inside the [`Waker`] when awaiting and inside `rayon::spawn` when running.
72///
73/// # Examples
74///
75/// ```
76/// # use zng_task::{self as task, *, rayon::iter::*};
77/// # use zng_var::*;
78/// # struct SomeStruct { sum_response: ResponseVar<usize> }
79/// # impl SomeStruct {
80/// fn on_event(&mut self) {
81///     let (responder, response) = response_var();
82///     self.sum_response = response;
83///
84///     task::spawn(async move {
85///         let r = (0..1000).into_par_iter().map(|i| i * i).sum();
86///
87///         responder.respond(r);
88///     });
89/// }
90///
91/// fn on_update(&mut self) {
92///     if let Some(result) = self.sum_response.rsp_new() {
93///         println!("sum of squares 0..1000: {result}");
94///     }
95/// }
96/// # }
97/// ```
98///
99/// The example uses the `rayon` parallel iterator to compute a result and uses a [`response_var`] to send the result to the UI.
100/// The task captures the caller [`LocalContext`] so the response variable will set correctly.
101///
102/// Note that this function is the most basic way to spawn a parallel task where you must setup channels to the rest of the app yourself,
103/// you can use [`respond`] to avoid having to manually set a response, or [`run`] to `.await` the result.
104///
105/// # Panic Handling
106///
107/// If the `task` panics the panic message is logged as an error, and can observed using [`set_spawn_panic_handler`]. It
108/// is otherwise ignored.
109///
110/// # Unwind Safety
111///
112/// This function disables the [unwind safety validation], meaning that in case of a panic shared
113/// data can end-up in an invalid, but still memory safe, state. If you are worried about that only use
114/// poisoning mutexes or atomics to mutate shared data or use [`run_catch`] to detect a panic or [`run`]
115/// to propagate a panic.
116///
117/// [unwind safety validation]: std::panic::UnwindSafe
118/// [`Waker`]: std::task::Waker
119/// [`rayon`]: https://docs.rs/rayon
120/// [`LocalContext`]: zng_app_context::LocalContext
121/// [`response_var`]: zng_var::response_var
122pub fn spawn<F>(task: impl IntoFuture<IntoFuture = F>)
123where
124    F: Future<Output = ()> + Send + 'static,
125{
126    Arc::new(RayonTask {
127        ctx: LocalContext::capture(),
128        fut: Mutex::new(Some(Box::pin(task.into_future()))),
129    })
130    .poll()
131}
132
133/// Polls the `task` once immediately on the calling thread, if the `task` is pending, continues execution in [`spawn`].
134pub fn poll_spawn<F>(task: impl IntoFuture<IntoFuture = F>)
135where
136    F: Future<Output = ()> + Send + 'static,
137{
138    struct PollRayonTask {
139        fut: Mutex<Option<(RayonSpawnFut, Option<LocalContext>)>>,
140    }
141    impl PollRayonTask {
142        // start task in calling thread
143        fn poll(self: Arc<Self>) {
144            let mut task = self.fut.lock();
145            let (mut t, _) = task.take().unwrap();
146
147            let waker = self.clone().into();
148
149            match t.as_mut().poll(&mut std::task::Context::from_waker(&waker)) {
150                Poll::Ready(()) => {}
151                Poll::Pending => {
152                    let ctx = LocalContext::capture();
153                    *task = Some((t, Some(ctx)));
154                }
155            }
156        }
157    }
158    impl std::task::Wake for PollRayonTask {
159        fn wake(self: Arc<Self>) {
160            // continue task in spawn threads
161            if let Some((task, Some(ctx))) = self.fut.lock().take() {
162                Arc::new(RayonTask {
163                    ctx,
164                    fut: Mutex::new(Some(Box::pin(task))),
165                })
166                .poll();
167            }
168        }
169    }
170
171    Arc::new(PollRayonTask {
172        fut: Mutex::new(Some((Box::pin(task.into_future()), None))),
173    })
174    .poll()
175}
176
177type RayonSpawnFut = Pin<Box<dyn Future<Output = ()> + Send>>;
178
179// A future that is its own waker that polls inside rayon spawn tasks.
180struct RayonTask {
181    ctx: LocalContext,
182    fut: Mutex<Option<RayonSpawnFut>>,
183}
184impl RayonTask {
185    fn poll(self: Arc<Self>) {
186        ::rayon::spawn(move || {
187            // this `Option<Fut>` dance is used to avoid a `poll` after `Ready` or panic.
188            let mut task = self.fut.lock();
189            if let Some(mut t) = task.take() {
190                let waker = self.clone().into();
191
192                // load app context
193                self.ctx.clone().with_context(move || {
194                    let r = panic::catch_unwind(panic::AssertUnwindSafe(move || {
195                        // poll future
196                        if t.as_mut().poll(&mut std::task::Context::from_waker(&waker)).is_pending() {
197                            // not done
198                            *task = Some(t);
199                        }
200                    }));
201                    if let Err(p) = r {
202                        let p = TaskPanicError::new(p);
203                        tracing::error!("panic in `task::spawn`: {}", p.panic_str().unwrap_or(""));
204                        on_spawn_panic(p);
205                    }
206                });
207            }
208        })
209    }
210}
211impl std::task::Wake for RayonTask {
212    fn wake(self: Arc<Self>) {
213        self.poll()
214    }
215}
216
217/// Rayon join with local context.
218///
219/// This function captures the [`LocalContext`] of the calling thread and propagates it to the threads that run the
220/// operations.
221///
222/// See `rayon::join` for more details about join.
223///
224/// [`LocalContext`]: zng_app_context::LocalContext
225pub fn join<A, B, RA, RB>(op_a: A, op_b: B) -> (RA, RB)
226where
227    A: FnOnce() -> RA + Send,
228    B: FnOnce() -> RB + Send,
229    RA: Send,
230    RB: Send,
231{
232    self::join_context(move |_| op_a(), move |_| op_b())
233}
234
235/// Rayon join context with local context.
236///
237/// This function captures the [`LocalContext`] of the calling thread and propagates it to the threads that run the
238/// operations.
239///
240/// See `rayon::join_context` for more details about join.
241///
242/// [`LocalContext`]: zng_app_context::LocalContext
243pub fn join_context<A, B, RA, RB>(op_a: A, op_b: B) -> (RA, RB)
244where
245    A: FnOnce(::rayon::FnContext) -> RA + Send,
246    B: FnOnce(::rayon::FnContext) -> RB + Send,
247    RA: Send,
248    RB: Send,
249{
250    let ctx = LocalContext::capture();
251    let ctx = &ctx;
252    ::rayon::join_context(
253        move |a| {
254            if a.migrated() {
255                ctx.clone().with_context(|| op_a(a))
256            } else {
257                op_a(a)
258            }
259        },
260        move |b| {
261            if b.migrated() {
262                ctx.clone().with_context(|| op_b(b))
263            } else {
264                op_b(b)
265            }
266        },
267    )
268}
269
270/// Rayon scope with local context.
271///
272/// This function captures the [`LocalContext`] of the calling thread and propagates it to the threads that run the
273/// operations.
274///
275/// See `rayon::scope` for more details about scope.
276///
277/// [`LocalContext`]: zng_app_context::LocalContext
278pub fn scope<'scope, OP, R>(op: OP) -> R
279where
280    OP: FnOnce(ScopeCtx<'_, 'scope>) -> R + Send,
281    R: Send,
282{
283    let ctx = LocalContext::capture();
284
285    // Cast `&'_ ctx` to `&'scope ctx` to "inject" the context in the scope.
286    // Is there a better way to do this? I hope so.
287    //
288    // SAFETY:
289    // * We are extending `'_` to `'scope`, that is one of the documented valid usages of `transmute`.
290    // * No use after free because `rayon::scope` joins all threads before returning and we only drop `ctx` after.
291    let ctx_ref: &'_ LocalContext = &ctx;
292    let ctx_scope_ref: &'scope LocalContext = unsafe { std::mem::transmute(ctx_ref) };
293
294    let r = ::rayon::scope(move |s| {
295        op(ScopeCtx {
296            scope: s,
297            ctx: ctx_scope_ref,
298        })
299    });
300
301    drop(ctx);
302
303    r
304}
305
306/// Represents a fork-join scope which can be used to spawn any number of tasks that run in the caller's thread context.
307///
308/// See [`scope`] for more details.
309#[derive(Clone, Copy, Debug)]
310pub struct ScopeCtx<'a, 'scope: 'a> {
311    scope: &'a ::rayon::Scope<'scope>,
312    ctx: &'scope LocalContext,
313}
314impl<'a, 'scope: 'a> ScopeCtx<'a, 'scope> {
315    /// Spawns a job into the fork-join scope `self`. The job runs in the captured thread context.
316    ///
317    /// See `rayon::Scope::spawn` for more details.
318    pub fn spawn<F>(self, f: F)
319    where
320        F: FnOnce(ScopeCtx<'_, 'scope>) + Send + 'scope,
321    {
322        let ctx = self.ctx;
323        self.scope
324            .spawn(move |s| ctx.clone().with_context(move || f(ScopeCtx { scope: s, ctx })));
325    }
326}
327
328/// Spawn a parallel async task that can also be `.await` for the task result.
329///
330/// # Parallel
331///
332/// The task runs in the primary [`rayon`] thread-pool, every [`poll`](Future::poll) happens inside a call to `rayon::spawn`.
333///
334/// You can use parallel iterators, `join` or any of rayon's utilities inside `task` to make it multi-threaded,
335/// otherwise it will run in a single thread at a time, still not blocking the UI.
336///
337/// The [`rayon`] crate is re-exported in `task::rayon` for convenience and compatibility.
338///
339/// # Async
340///
341/// The `task` is also a future so you can `.await`, after each `.await` the task continues executing in whatever `rayon` thread
342/// is free, so the `task` should either be doing CPU intensive work or awaiting, blocking IO operations
343/// block the thread from being used by other tasks reducing overall performance. You can use [`wait`] for IO
344/// or blocking operations and for networking you can use any of the async crates, as long as they start their own *event reactor*.
345///
346/// The `task` lives inside the [`Waker`] when awaiting and inside `rayon::spawn` when running.
347///
348/// # Examples
349///
350/// ```
351/// # use zng_task::{self as task, rayon::iter::*};
352/// # struct SomeStruct { sum: usize }
353/// # async fn read_numbers() -> Vec<usize> { vec![] }
354/// # impl SomeStruct {
355/// async fn on_event(&mut self) {
356///     self.sum = task::run(async { read_numbers().await.par_iter().map(|i| i * i).sum() }).await;
357/// }
358/// # }
359/// ```
360///
361/// The example `.await` for some numbers and then uses a parallel iterator to compute a result, this all runs in parallel
362/// because it is inside a `run` task. The task result is then `.await` inside one of the UI async tasks. Note that the
363/// task captures the caller [`LocalContext`] so you can interact with variables and UI services directly inside the task too.
364///
365/// # Cancellation
366///
367/// The task starts running immediately, awaiting the returned future merely awaits for a message from the worker threads and
368/// that means the `task` future is not owned by the returned future. Usually to *cancel* a future you only need to drop it,
369/// in this task dropping the returned future will only drop the `task` once it reaches a `.await` point and detects that the
370/// result channel is disconnected.
371///
372/// If you want to deterministically known that the `task` was cancelled use a cancellation signal.
373///
374/// # Panic Propagation
375///
376/// If the `task` panics the panic is resumed in the awaiting thread using [`resume_unwind`]. You
377/// can use [`run_catch`] to get the panic as an error instead.
378///
379/// [`resume_unwind`]: panic::resume_unwind
380/// [`Waker`]: std::task::Waker
381/// [`rayon`]: https://docs.rs/rayon
382/// [`LocalContext`]: zng_app_context::LocalContext
383pub async fn run<R, T>(task: impl IntoFuture<IntoFuture = T>) -> R
384where
385    R: Send + 'static,
386    T: Future<Output = R> + Send + 'static,
387{
388    match run_catch(task).await {
389        Ok(r) => r,
390        Err(p) => panic::resume_unwind(p.payload),
391    }
392}
393
394/// Like [`run`] but catches panics.
395///
396/// This task works the same and has the same utility as [`run`], except if returns panic messages
397/// as an error instead of propagating the panic.
398///
399/// # Unwind Safety
400///
401/// This function disables the [unwind safety validation], meaning that in case of a panic shared
402/// data can end-up in an invalid, but still memory safe, state. If you are worried about that only use
403/// poisoning mutexes or atomics to mutate shared data or discard all shared data used in the `task`
404/// if this function returns an error.
405///
406/// [unwind safety validation]: std::panic::UnwindSafe
407pub async fn run_catch<R, T>(task: impl IntoFuture<IntoFuture = T>) -> Result<R, TaskPanicError>
408where
409    R: Send + 'static,
410    T: Future<Output = R> + Send + 'static,
411{
412    type Fut<R> = Pin<Box<dyn Future<Output = R> + Send>>;
413
414    // A future that is its own waker that polls inside the rayon primary thread-pool.
415    struct RayonCatchTask<R> {
416        ctx: LocalContext,
417        fut: Mutex<Option<Fut<R>>>,
418        sender: flume::Sender<Result<R, TaskPanicError>>,
419    }
420    impl<R: Send + 'static> RayonCatchTask<R> {
421        fn poll(self: Arc<Self>) {
422            let sender = self.sender.clone();
423            if sender.is_disconnected() {
424                return; // cancel.
425            }
426            ::rayon::spawn(move || {
427                // this `Option<Fut>` dance is used to avoid a `poll` after `Ready` or panic.
428                let mut task = self.fut.lock();
429                if let Some(mut t) = task.take() {
430                    let waker = self.clone().into();
431                    let mut cx = std::task::Context::from_waker(&waker);
432
433                    self.ctx.clone().with_context(|| {
434                        let r = panic::catch_unwind(panic::AssertUnwindSafe(|| t.as_mut().poll(&mut cx)));
435                        match r {
436                            Ok(Poll::Ready(r)) => {
437                                drop(task);
438                                let _ = sender.send(Ok(r));
439                            }
440                            Ok(Poll::Pending) => {
441                                *task = Some(t);
442                            }
443                            Err(p) => {
444                                drop(task);
445                                let _ = sender.send(Err(TaskPanicError::new(p)));
446                            }
447                        }
448                    });
449                }
450            })
451        }
452    }
453    impl<R: Send + 'static> std::task::Wake for RayonCatchTask<R> {
454        fn wake(self: Arc<Self>) {
455            self.poll()
456        }
457    }
458
459    let (sender, receiver) = channel::bounded(1);
460
461    Arc::new(RayonCatchTask {
462        ctx: LocalContext::capture(),
463        fut: Mutex::new(Some(Box::pin(task.into_future()))),
464        sender: sender.into(),
465    })
466    .poll();
467
468    receiver.recv().await.unwrap()
469}
470
471/// Spawn a parallel async task that will send its result to a [`ResponseVar<R>`].
472///
473/// The [`run`] documentation explains how `task` is *parallel* and *async*. The `task` starts executing immediately.
474///
475/// # Examples
476///
477/// ```
478/// # use zng_task::{self as task, rayon::iter::*};
479/// # use zng_var::*;
480/// # struct SomeStruct { sum_response: ResponseVar<usize> }
481/// # async fn read_numbers() -> Vec<usize> { vec![] }
482/// # impl SomeStruct {
483/// fn on_event(&mut self) {
484///     self.sum_response = task::respond(async { read_numbers().await.par_iter().map(|i| i * i).sum() });
485/// }
486///
487/// fn on_update(&mut self) {
488///     if let Some(result) = self.sum_response.rsp_new() {
489///         println!("sum of squares: {result}");
490///     }
491/// }
492/// # }
493/// ```
494///
495/// The example `.await` for some numbers and then uses a parallel iterator to compute a result. The result is send to
496/// `sum_response` that is a [`ResponseVar<R>`].
497///
498/// # Cancellation
499///
500/// Dropping the [`ResponseVar<R>`] does not cancel the `task`, it will still run to completion.
501///
502/// # Panic Handling
503///
504/// If the `task` panics the panic is logged as an error and resumed in the response var modify closure.
505///
506/// [`resume_unwind`]: panic::resume_unwind
507/// [`ResponseVar<R>`]: zng_var::ResponseVar
508/// [`response_var`]: zng_var::response_var
509pub fn respond<R, F>(task: F) -> ResponseVar<R>
510where
511    R: VarValue,
512    F: Future<Output = R> + Send + 'static,
513{
514    type Fut<R> = Pin<Box<dyn Future<Output = R> + Send>>;
515
516    let (responder, response) = response_var();
517
518    // A future that is its own waker that polls inside the rayon primary thread-pool.
519    struct RayonRespondTask<R: VarValue> {
520        ctx: LocalContext,
521        fut: Mutex<Option<Fut<R>>>,
522        responder: zng_var::ResponderVar<R>,
523    }
524    impl<R: VarValue> RayonRespondTask<R> {
525        fn poll(self: Arc<Self>) {
526            let responder = self.responder.clone();
527            if responder.strong_count() == 2 {
528                return; // cancel.
529            }
530            ::rayon::spawn(move || {
531                // this `Option<Fut>` dance is used to avoid a `poll` after `Ready` or panic.
532                let mut task = self.fut.lock();
533                if let Some(mut t) = task.take() {
534                    let waker = self.clone().into();
535                    let mut cx = std::task::Context::from_waker(&waker);
536
537                    self.ctx.clone().with_context(|| {
538                        let r = panic::catch_unwind(panic::AssertUnwindSafe(|| t.as_mut().poll(&mut cx)));
539                        match r {
540                            Ok(Poll::Ready(r)) => {
541                                drop(task);
542
543                                responder.respond(r);
544                            }
545                            Ok(Poll::Pending) => {
546                                *task = Some(t);
547                            }
548                            Err(p) => {
549                                let p = TaskPanicError::new(p);
550                                tracing::error!("panic in `task::respond`: {}", p.panic_str().unwrap_or(""));
551                                drop(task);
552                                responder.modify(move |_| panic::resume_unwind(p.payload));
553                            }
554                        }
555                    });
556                }
557            })
558        }
559    }
560    impl<R: VarValue> std::task::Wake for RayonRespondTask<R> {
561        fn wake(self: Arc<Self>) {
562            self.poll()
563        }
564    }
565
566    Arc::new(RayonRespondTask {
567        ctx: LocalContext::capture(),
568        fut: Mutex::new(Some(Box::pin(task))),
569        responder,
570    })
571    .poll();
572
573    response
574}
575
576/// Polls the `task` once immediately on the calling thread, if the `task` is ready returns the response already set,
577/// if the `task` is pending continues execution like [`respond`].
578pub fn poll_respond<R, F>(task: impl IntoFuture<IntoFuture = F>) -> ResponseVar<R>
579where
580    R: VarValue,
581    F: Future<Output = R> + Send + 'static,
582{
583    enum QuickResponse<R: VarValue> {
584        Quick(Option<R>),
585        Response(zng_var::ResponderVar<R>),
586    }
587    let task = task.into_future();
588    let q = Arc::new(Mutex::new(QuickResponse::Quick(None)));
589    poll_spawn(zng_clone_move::async_clmv!(q, {
590        let rsp = task.await;
591
592        match &mut *q.lock() {
593            QuickResponse::Quick(q) => *q = Some(rsp),
594            QuickResponse::Response(r) => r.respond(rsp),
595        }
596    }));
597
598    let mut q = q.lock();
599    match &mut *q {
600        QuickResponse::Quick(q) if q.is_some() => response_done_var(q.take().unwrap()),
601        _ => {
602            let (responder, response) = response_var();
603            *q = QuickResponse::Response(responder);
604            response
605        }
606    }
607}
608
609/// Create a parallel `task` that blocks awaiting for an IO operation, the `task` starts on the first `.await`.
610///
611/// # Parallel
612///
613/// The `task` runs in the [`blocking`] thread-pool which is optimized for awaiting blocking operations.
614/// If the `task` is computation heavy you should use [`run`] and then `wait` inside that task for the
615/// parts that are blocking.
616///
617/// # Examples
618///
619/// ```
620/// # fn main() { }
621/// # use zng_task as task;
622/// # async fn example() {
623/// task::wait(|| std::fs::read_to_string("file.txt")).await
624/// # ; }
625/// ```
626///
627/// The example reads a file, that is a blocking file IO operation, most of the time is spend waiting for the operating system,
628/// so we offload this to a `wait` task. The task can be `.await` inside a [`run`] task or inside one of the UI tasks
629/// like in a async event handler.
630///
631/// # Async Read/Write
632///
633/// For [`std::io::Read`] and [`std::io::Write`] operations you can also use [`io`] and [`fs`] alternatives when you don't
634/// have or want the full file in memory or when you want to apply multiple operations to the file.
635///
636/// # Panic Propagation
637///
638/// If the `task` panics the panic is resumed in the awaiting thread using [`resume_unwind`]. You
639/// can use [`wait_catch`] to get the panic as an error instead.
640///
641/// [`blocking`]: https://docs.rs/blocking
642/// [`resume_unwind`]: panic::resume_unwind
643pub async fn wait<T, F>(task: F) -> T
644where
645    F: FnOnce() -> T + Send + 'static,
646    T: Send + 'static,
647{
648    match wait_catch(task).await {
649        Ok(r) => r,
650        Err(p) => panic::resume_unwind(p.payload),
651    }
652}
653
654/// Like [`wait`] but catches panics.
655///
656/// This task works the same and has the same utility as [`wait`], except if returns panic messages
657/// as an error instead of propagating the panic.
658///
659/// # Unwind Safety
660///
661/// This function disables the [unwind safety validation], meaning that in case of a panic shared
662/// data can end-up in an invalid, but still memory safe, state. If you are worried about that only use
663/// poisoning mutexes or atomics to mutate shared data or discard all shared data used in the `task`
664/// if this function returns an error.
665///
666/// [unwind safety validation]: std::panic::UnwindSafe
667pub async fn wait_catch<T, F>(task: F) -> Result<T, TaskPanicError>
668where
669    F: FnOnce() -> T + Send + 'static,
670    T: Send + 'static,
671{
672    let mut ctx = LocalContext::capture();
673    blocking::unblock(move || ctx.with_context(move || panic::catch_unwind(panic::AssertUnwindSafe(task))))
674        .await
675        .map_err(TaskPanicError::new)
676}
677
678/// Fire and forget a [`wait`] task. The `task` starts executing immediately.
679///
680/// # Panic Handling
681///
682/// If the `task` panics the panic message is logged as an error, and can observed using [`set_spawn_panic_handler`]. It
683/// is otherwise ignored.
684///
685/// # Unwind Safety
686///
687/// This function disables the [unwind safety validation], meaning that in case of a panic shared
688/// data can end-up in an invalid (still memory safe) state. If you are worried about that only use
689/// poisoning mutexes or atomics to mutate shared data or use [`wait_catch`] to detect a panic or [`wait`]
690/// to propagate a panic.
691///
692/// [unwind safety validation]: std::panic::UnwindSafe
693pub fn spawn_wait<F>(task: F)
694where
695    F: FnOnce() + Send + 'static,
696{
697    spawn(async move {
698        if let Err(p) = wait_catch(task).await {
699            tracing::error!("parallel `spawn_wait` task panicked: {}", p.panic_str().unwrap_or(""));
700            on_spawn_panic(p);
701        }
702    });
703}
704
705/// Like [`spawn_wait`], but the task will send its result to a [`ResponseVar<R>`].
706///
707/// # Cancellation
708///
709/// Dropping the [`ResponseVar<R>`] does not cancel the `task`, it will still run to completion.
710///
711/// # Panic Handling
712///
713/// If the `task` panics the panic is logged as an error and resumed in the response var modify closure.
714pub fn wait_respond<R, F>(task: F) -> ResponseVar<R>
715where
716    R: VarValue,
717    F: FnOnce() -> R + Send + 'static,
718{
719    let (responder, response) = response_var();
720    spawn_wait(move || match panic::catch_unwind(panic::AssertUnwindSafe(task)) {
721        Ok(r) => responder.respond(r),
722        Err(p) => {
723            let p = TaskPanicError::new(p);
724            tracing::error!("panic in `task::wait_respond`: {}", p.panic_str().unwrap_or(""));
725            responder.modify(move |_| panic::resume_unwind(p.payload));
726        }
727    });
728    response
729}
730
731/// Blocks the thread until the `task` future finishes.
732///
733/// The crate [`futures-lite`] is used to execute the task.
734///
735/// # Examples
736///
737/// Test a [`run`] call:
738///
739/// ```
740/// use zng_task as task;
741/// # use zng_unit::*;
742/// # async fn foo(u: u8) -> Result<u8, ()> { task::deadline(1.ms()).await; Ok(u) }
743///
744/// # #[test]
745/// # fn __() { }
746/// pub fn run_ok() {
747///     let r = task::block_on(task::run(async { foo(32).await }));
748///
749///     # let value =
750///     r.expect("foo(32) was not Ok");
751///     # assert_eq!(32, value);
752/// }
753/// # run_ok();
754/// ```
755///
756/// # No App Context
757///
758/// If this is called inside an app thread a warning is logged and the app context is removed,
759/// the `task` never runs in an app context. This is done to avoid deadlocks where tasks depend
760/// on app updates to complete.
761///
762/// You should never block an app thread anyway, use `UPDATES.run` to run arbitrary futures, or
763/// `async_hn!` to declare async event handlers.
764///
765/// [`futures-lite`]: https://docs.rs/futures-lite/
766pub fn block_on<F>(task: impl IntoFuture<IntoFuture = F>) -> F::Output
767where
768    F: Future,
769{
770    let task = task.into_future();
771
772    if zng_app_context::LocalContext::current_app().is_some() {
773        tracing::warn!("cannot `block_on` in an app context, task will not run in context");
774
775        zng_app_context::LocalContext::new().with_context(|| futures_lite::future::block_on(task))
776    } else {
777        futures_lite::future::block_on(task)
778    }
779}
780
781/// Continuous poll the `task` until if finishes.
782///
783/// This function is useful for implementing some async tests only, futures don't expect to be polled
784/// continuously. This function is only available in test builds.
785#[cfg(any(test, doc, feature = "test_util"))]
786pub fn spin_on<F>(task: impl IntoFuture<IntoFuture = F>) -> F::Output
787where
788    F: Future,
789{
790    use std::pin::pin;
791
792    let mut task = pin!(task.into_future());
793    block_on(future_fn(|cx| match task.as_mut().poll(cx) {
794        Poll::Ready(r) => Poll::Ready(r),
795        Poll::Pending => {
796            cx.waker().wake_by_ref();
797            Poll::Pending
798        }
799    }))
800}
801
802/// Executor used in async doc tests.
803///
804/// If `spin` is `true` the [`spin_on`] executor is used with a timeout of 500 milliseconds.
805/// IF `spin` is `false` the [`block_on`] executor is used with a timeout of 5 seconds.
806#[cfg(any(test, doc, feature = "test_util"))]
807pub fn doc_test<F>(spin: bool, task: impl IntoFuture<IntoFuture = F>) -> F::Output
808where
809    F: Future,
810{
811    use zng_unit::TimeUnits;
812
813    if spin {
814        spin_on(with_deadline(task, 500.ms())).expect("async doc-test timeout")
815    } else {
816        block_on(with_deadline(task, 5.secs())).expect("async doc-test timeout")
817    }
818}
819
820/// A future that is [`Pending`] once and wakes the current task.
821///
822/// After the first `.await` the future is always [`Ready`] and on the first `.await` it calls [`wake`].
823///
824/// [`Pending`]: std::task::Poll::Pending
825/// [`Ready`]: std::task::Poll::Ready
826/// [`wake`]: std::task::Waker::wake
827pub async fn yield_now() {
828    struct YieldNowFut(bool);
829    impl Future for YieldNowFut {
830        type Output = ();
831
832        fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
833            if self.0 {
834                Poll::Ready(())
835            } else {
836                self.0 = true;
837                cx.waker().wake_by_ref();
838                Poll::Pending
839            }
840        }
841    }
842
843    YieldNowFut(false).await
844}
845
846/// A future that is [`Pending`] until the `deadline` is reached.
847///
848/// # Examples
849///
850/// Await 5 seconds in a [`spawn`] parallel task:
851///
852/// ```
853/// use zng_task as task;
854/// use zng_unit::*;
855///
856/// task::spawn(async {
857///     println!("waiting 5 seconds..");
858///     task::deadline(5.secs()).await;
859///     println!("5 seconds elapsed.")
860/// });
861/// ```
862///
863/// The future runs on an app provider timer executor, or on the [`futures_timer`] by default.
864///
865/// Note that deadlines from [`Duration`](std::time::Duration) starts *counting* at the moment this function is called,
866/// not at the moment of the first `.await` call.
867///
868/// [`Pending`]: std::task::Poll::Pending
869/// [`futures_timer`]: https://docs.rs/futures-timer
870#[doc(alias = "timeout")]
871#[doc(alias = "timer")]
872pub fn deadline(deadline: impl Into<Deadline>) -> Pin<Box<dyn Future<Output = ()> + Send + Sync>> {
873    let deadline = deadline.into();
874    if zng_app_context::LocalContext::current_app().is_some() {
875        DEADLINE_SV.read().0(deadline)
876    } else {
877        default_deadline(deadline)
878    }
879}
880
881app_local! {
882    static DEADLINE_SV: (DeadlineService, bool) = const { (default_deadline, false) };
883}
884
885type DeadlineService = fn(Deadline) -> Pin<Box<dyn Future<Output = ()> + Send + Sync>>;
886
887fn default_deadline(deadline: Deadline) -> Pin<Box<dyn Future<Output = ()> + Send + Sync>> {
888    if let Some(timeout) = deadline.time_left() {
889        Box::pin(futures_timer::Delay::new(timeout))
890    } else {
891        Box::pin(std::future::ready(()))
892    }
893}
894
895/// Deadline APP integration.
896#[expect(non_camel_case_types)]
897pub struct DEADLINE_APP;
898
899impl DEADLINE_APP {
900    /// Called by the app implementer to setup the [`deadline`] executor.
901    ///
902    /// If no app calls this the [`futures_timer`] executor is used.
903    ///
904    /// [`futures_timer`]: https://docs.rs/futures-timer
905    ///
906    /// # Panics
907    ///
908    /// Panics if called more than once for the same app.
909    pub fn init_deadline_service(&self, service: DeadlineService) {
910        let (prev, already_set) = mem::replace(&mut *DEADLINE_SV.write(), (service, true));
911        if already_set {
912            *DEADLINE_SV.write() = (prev, true);
913            panic!("deadline service already inited for this app");
914        }
915    }
916}
917
918/// Implements a [`Future`] from a closure.
919///
920/// # Examples
921///
922/// A future that is ready with a closure returns `Some(R)`.
923///
924/// ```
925/// use std::task::Poll;
926/// use zng_task as task;
927///
928/// async fn ready_some<R>(mut closure: impl FnMut() -> Option<R>) -> R {
929///     task::future_fn(|cx| match closure() {
930///         Some(r) => Poll::Ready(r),
931///         None => Poll::Pending,
932///     })
933///     .await
934/// }
935/// ```
936pub async fn future_fn<T, F>(fn_: F) -> T
937where
938    F: FnMut(&mut std::task::Context) -> Poll<T>,
939{
940    struct PollFn<F>(F);
941    impl<F> Unpin for PollFn<F> {}
942    impl<T, F: FnMut(&mut std::task::Context<'_>) -> Poll<T>> Future for PollFn<F> {
943        type Output = T;
944
945        fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
946            (self.0)(cx)
947        }
948    }
949    PollFn(fn_).await
950}
951
952/// Error when [`with_deadline`] reach a time limit before a task finishes.
953#[derive(Debug, Clone, Copy)]
954#[non_exhaustive]
955pub struct DeadlineError {}
956impl fmt::Display for DeadlineError {
957    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
958        write!(f, "reached deadline")
959    }
960}
961impl std::error::Error for DeadlineError {}
962
963/// Add a [`deadline`] to a future.
964///
965/// Returns the `fut` output or [`DeadlineError`] if the deadline elapses first.
966pub async fn with_deadline<O, F: Future<Output = O>>(
967    fut: impl IntoFuture<IntoFuture = F>,
968    deadline: impl Into<Deadline>,
969) -> Result<F::Output, DeadlineError> {
970    let deadline = deadline.into();
971    any!(async { Ok(fut.await) }, async {
972        self::deadline(deadline).await;
973        Err(DeadlineError {})
974    })
975    .await
976}
977
978/// <span data-del-macro-root></span> A future that *zips* other futures.
979///
980/// The macro input is a comma separated list of future expressions. The macro output is a future
981/// that when ".awaited" produces a tuple of results in the same order as the inputs.
982///
983/// At least one input future is required and any number of futures is accepted. For more than
984/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
985/// some IDEs.
986///
987/// Each input must implement [`IntoFuture`]. Note that each input must be known at compile time, use the [`fn@all`] async
988/// function to await on all futures in a dynamic list of futures.
989///
990/// # Examples
991///
992/// Await for three different futures to complete:
993///
994/// ```
995/// use zng_task as task;
996///
997/// # task::doc_test(false, async {
998/// let (a, b, c) = task::all!(task::run(async { 'a' }), task::wait(|| "b"), async { b"c" }).await;
999/// # });
1000/// ```
1001#[macro_export]
1002macro_rules! all {
1003    ($fut0:expr $(,)?) => { $crate::__all! { fut0: $fut0; } };
1004    ($fut0:expr, $fut1:expr $(,)?) => {
1005        $crate::__all! {
1006            fut0: $fut0;
1007            fut1: $fut1;
1008        }
1009    };
1010    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1011        $crate::__all! {
1012            fut0: $fut0;
1013            fut1: $fut1;
1014            fut2: $fut2;
1015        }
1016    };
1017    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1018        $crate::__all! {
1019            fut0: $fut0;
1020            fut1: $fut1;
1021            fut2: $fut2;
1022            fut3: $fut3;
1023        }
1024    };
1025    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1026        $crate::__all! {
1027            fut0: $fut0;
1028            fut1: $fut1;
1029            fut2: $fut2;
1030            fut3: $fut3;
1031            fut4: $fut4;
1032        }
1033    };
1034    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1035        $crate::__all! {
1036            fut0: $fut0;
1037            fut1: $fut1;
1038            fut2: $fut2;
1039            fut3: $fut3;
1040            fut4: $fut4;
1041            fut5: $fut5;
1042        }
1043    };
1044    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1045        $crate::__all! {
1046            fut0: $fut0;
1047            fut1: $fut1;
1048            fut2: $fut2;
1049            fut3: $fut3;
1050            fut4: $fut4;
1051            fut5: $fut5;
1052            fut6: $fut6;
1053        }
1054    };
1055    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1056        $crate::__all! {
1057            fut0: $fut0;
1058            fut1: $fut1;
1059            fut2: $fut2;
1060            fut3: $fut3;
1061            fut4: $fut4;
1062            fut5: $fut5;
1063            fut6: $fut6;
1064            fut7: $fut7;
1065        }
1066    };
1067    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__all; $($fut),+ } }
1068}
1069
1070#[doc(hidden)]
1071#[macro_export]
1072macro_rules! __all {
1073    ($($ident:ident: $fut:expr;)+) => {
1074        {
1075            $(let mut $ident = $crate::FutureOrOutput::Future(std::future::IntoFuture::into_future($fut));)+
1076            $crate::future_fn(move |cx| {
1077                use std::task::Poll;
1078
1079                let mut pending = false;
1080
1081                $(
1082                    if let $crate::FutureOrOutput::Future(fut) = &mut $ident {
1083                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1084                        // Future::poll call, so it will not move.
1085                        let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1086                        if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1087                            $ident = $crate::FutureOrOutput::Output(r);
1088                        } else {
1089                            pending = true;
1090                        }
1091                    }
1092                )+
1093
1094                if pending {
1095                    Poll::Pending
1096                } else {
1097                    Poll::Ready(($($ident.take_output()),+))
1098                }
1099            })
1100        }
1101    }
1102}
1103
1104#[doc(hidden)]
1105pub enum FutureOrOutput<F: Future> {
1106    Future(F),
1107    Output(F::Output),
1108    Taken,
1109}
1110impl<F: Future> FutureOrOutput<F> {
1111    pub fn take_output(&mut self) -> F::Output {
1112        match std::mem::replace(self, Self::Taken) {
1113            FutureOrOutput::Output(o) => o,
1114            _ => unreachable!(),
1115        }
1116    }
1117}
1118
1119/// A future that awaits on all `futures` at the same time and returns all results when all futures are ready.
1120///
1121/// This is the dynamic version of [`all!`].
1122pub async fn all<F: IntoFuture>(futures: impl IntoIterator<Item = F>) -> Vec<F::Output> {
1123    let mut futures: Vec<_> = futures.into_iter().map(|f| FutureOrOutput::Future(f.into_future())).collect();
1124    future_fn(move |cx| {
1125        let mut pending = false;
1126        for input in &mut futures {
1127            if let FutureOrOutput::Future(fut) = input {
1128                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1129                // Future::poll call, so it will not move.
1130                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1131                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1132                    *input = FutureOrOutput::Output(r);
1133                } else {
1134                    pending = true;
1135                }
1136            }
1137        }
1138
1139        if pending {
1140            Poll::Pending
1141        } else {
1142            Poll::Ready(futures.iter_mut().map(FutureOrOutput::take_output).collect())
1143        }
1144    })
1145    .await
1146}
1147
1148/// <span data-del-macro-root></span> A future that awaits for the first future that is ready.
1149///
1150/// The macro input is comma separated list of future expressions, the futures must
1151/// all have the same output type. The macro output is a future that when ".awaited" produces
1152/// a single output type instance returned by the first input future that completes.
1153///
1154/// At least one input future is required and any number of futures is accepted. For more than
1155/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1156/// some IDEs.
1157///
1158/// If two futures are ready at the same time the result of the first future in the input list is used.
1159/// After one future is ready the other futures are not polled again and are dropped.
1160///
1161/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1162/// known at compile time, use the [`fn@any`] async function to await on all futures in a dynamic list of futures.
1163///
1164/// # Examples
1165///
1166/// Await for the first of three futures to complete:
1167///
1168/// ```
1169/// use zng_task as task;
1170/// use zng_unit::*;
1171///
1172/// # task::doc_test(false, async {
1173/// let r = task::any!(
1174///     task::run(async {
1175///         task::deadline(300.ms()).await;
1176///         'a'
1177///     }),
1178///     task::wait(|| 'b'),
1179///     async {
1180///         task::deadline(300.ms()).await;
1181///         'c'
1182///     }
1183/// )
1184/// .await;
1185///
1186/// assert_eq!('b', r);
1187/// # });
1188/// ```
1189#[macro_export]
1190macro_rules! any {
1191    ($fut0:expr $(,)?) => { $crate::__any! { fut0: $fut0; } };
1192    ($fut0:expr, $fut1:expr $(,)?) => {
1193        $crate::__any! {
1194            fut0: $fut0;
1195            fut1: $fut1;
1196        }
1197    };
1198    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1199        $crate::__any! {
1200            fut0: $fut0;
1201            fut1: $fut1;
1202            fut2: $fut2;
1203        }
1204    };
1205    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1206        $crate::__any! {
1207            fut0: $fut0;
1208            fut1: $fut1;
1209            fut2: $fut2;
1210            fut3: $fut3;
1211        }
1212    };
1213    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1214        $crate::__any! {
1215            fut0: $fut0;
1216            fut1: $fut1;
1217            fut2: $fut2;
1218            fut3: $fut3;
1219            fut4: $fut4;
1220        }
1221    };
1222    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1223        $crate::__any! {
1224            fut0: $fut0;
1225            fut1: $fut1;
1226            fut2: $fut2;
1227            fut3: $fut3;
1228            fut4: $fut4;
1229            fut5: $fut5;
1230        }
1231    };
1232    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1233        $crate::__any! {
1234            fut0: $fut0;
1235            fut1: $fut1;
1236            fut2: $fut2;
1237            fut3: $fut3;
1238            fut4: $fut4;
1239            fut5: $fut5;
1240            fut6: $fut6;
1241        }
1242    };
1243    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1244        $crate::__any! {
1245            fut0: $fut0;
1246            fut1: $fut1;
1247            fut2: $fut2;
1248            fut3: $fut3;
1249            fut4: $fut4;
1250            fut5: $fut5;
1251            fut6: $fut6;
1252            fut7: $fut7;
1253        }
1254    };
1255    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__any; $($fut),+ } }
1256}
1257#[doc(hidden)]
1258#[macro_export]
1259macro_rules! __any {
1260    ($($ident:ident: $fut:expr;)+) => {
1261        {
1262            $(let mut $ident = std::future::IntoFuture::into_future($fut);)+
1263            $crate::future_fn(move |cx| {
1264                use std::task::Poll;
1265                $(
1266                    // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1267                    // Future::poll call, so it will not move.
1268                    let mut $ident = unsafe { std::pin::Pin::new_unchecked(&mut $ident) };
1269                    if let Poll::Ready(r) = $ident.as_mut().poll(cx) {
1270                        return Poll::Ready(r)
1271                    }
1272                )+
1273
1274                Poll::Pending
1275            })
1276        }
1277    }
1278}
1279#[doc(hidden)]
1280pub use zng_task_proc_macros::task_any_all as __proc_any_all;
1281
1282/// A future that awaits on all `futures` at the same time and returns the first result when the first future is ready.
1283///
1284/// This is the dynamic version of [`any!`].
1285pub async fn any<F: IntoFuture>(futures: impl IntoIterator<Item = F>) -> F::Output {
1286    let mut futures: Vec<_> = futures.into_iter().map(IntoFuture::into_future).collect();
1287    future_fn(move |cx| {
1288        for fut in &mut futures {
1289            // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1290            // Future::poll call, so it will not move.
1291            let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1292            if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1293                return Poll::Ready(r);
1294            }
1295        }
1296        Poll::Pending
1297    })
1298    .await
1299}
1300
1301/// <span data-del-macro-root></span> A future that waits for the first future that is ready with an `Ok(T)` result.
1302///
1303/// The macro input is comma separated list of future expressions, the futures must
1304/// all have the same output `Result<T, E>` type, but each can have a different `E`. The macro output is a future
1305/// that when ".awaited" produces a single output of type `Result<T, (E0, E1, ..)>` that is `Ok(T)` if any of the futures
1306/// is `Ok(T)` or is `Err((E0, E1, ..))` is all futures are `Err`.
1307///
1308/// At least one input future is required and any number of futures is accepted. For more than
1309/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1310/// some IDEs.
1311///
1312/// If two futures are ready and `Ok(T)` at the same time the result of the first future in the input list is used.
1313/// After one future is ready and `Ok(T)` the other futures are not polled again and are dropped. After a future
1314/// is ready and `Err(E)` it is also not polled again and dropped.
1315///
1316/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1317/// known at compile time, use the [`fn@any_ok`] async function to await on all futures in a dynamic list of futures.
1318///
1319/// # Examples
1320///
1321/// Await for the first of three futures to complete with `Ok`:
1322///
1323/// ```
1324/// use zng_task as task;
1325/// # #[derive(Debug, PartialEq)]
1326/// # pub struct FooError;
1327/// # task::doc_test(false, async {
1328/// let r = task::any_ok!(
1329///     task::run(async { Err::<char, _>("error") }),
1330///     task::wait(|| Ok::<_, FooError>('b')),
1331///     async { Err::<char, _>(FooError) }
1332/// )
1333/// .await;
1334///
1335/// assert_eq!(Ok('b'), r);
1336/// # });
1337/// ```
1338#[macro_export]
1339macro_rules! any_ok {
1340    ($fut0:expr $(,)?) => { $crate::__any_ok! { fut0: $fut0; } };
1341    ($fut0:expr, $fut1:expr $(,)?) => {
1342        $crate::__any_ok! {
1343            fut0: $fut0;
1344            fut1: $fut1;
1345        }
1346    };
1347    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1348        $crate::__any_ok! {
1349            fut0: $fut0;
1350            fut1: $fut1;
1351            fut2: $fut2;
1352        }
1353    };
1354    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1355        $crate::__any_ok! {
1356            fut0: $fut0;
1357            fut1: $fut1;
1358            fut2: $fut2;
1359            fut3: $fut3;
1360        }
1361    };
1362    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1363        $crate::__any_ok! {
1364            fut0: $fut0;
1365            fut1: $fut1;
1366            fut2: $fut2;
1367            fut3: $fut3;
1368            fut4: $fut4;
1369        }
1370    };
1371    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1372        $crate::__any_ok! {
1373            fut0: $fut0;
1374            fut1: $fut1;
1375            fut2: $fut2;
1376            fut3: $fut3;
1377            fut4: $fut4;
1378            fut5: $fut5;
1379        }
1380    };
1381    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1382        $crate::__any_ok! {
1383            fut0: $fut0;
1384            fut1: $fut1;
1385            fut2: $fut2;
1386            fut3: $fut3;
1387            fut4: $fut4;
1388            fut5: $fut5;
1389            fut6: $fut6;
1390        }
1391    };
1392    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1393        $crate::__any_ok! {
1394            fut0: $fut0;
1395            fut1: $fut1;
1396            fut2: $fut2;
1397            fut3: $fut3;
1398            fut4: $fut4;
1399            fut5: $fut5;
1400            fut6: $fut6;
1401            fut7: $fut7;
1402        }
1403    };
1404    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__any_ok; $($fut),+ } }
1405}
1406
1407#[doc(hidden)]
1408#[macro_export]
1409macro_rules! __any_ok {
1410    ($($ident:ident: $fut: expr;)+) => {
1411        {
1412            $(let mut $ident = $crate::FutureOrOutput::Future(std::future::IntoFuture::into_future($fut));)+
1413            $crate::future_fn(move |cx| {
1414                use std::task::Poll;
1415
1416                let mut pending = false;
1417
1418                $(
1419                    if let $crate::FutureOrOutput::Future(fut) = &mut $ident {
1420                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1421                        // Future::poll call, so it will not move.
1422                        let mut fut = unsafe { std::pin::Pin::new_unchecked(fut) };
1423                        if let Poll::Ready(r) = fut.as_mut().poll(cx) {
1424                            match r {
1425                                Ok(r) => return Poll::Ready(Ok(r)),
1426                                Err(e) => {
1427                                    $ident = $crate::FutureOrOutput::Output(Err(e));
1428                                }
1429                            }
1430                        } else {
1431                            pending = true;
1432                        }
1433                    }
1434                )+
1435
1436                if pending {
1437                    Poll::Pending
1438                } else {
1439                    Poll::Ready(Err((
1440                        $($ident.take_output().unwrap_err()),+
1441                    )))
1442                }
1443            })
1444        }
1445    }
1446}
1447
1448/// A future that awaits on all `futures` at the same time and returns when any future is `Ok(_)` or all are `Err(_)`.
1449///
1450/// This is the dynamic version of [`all_some!`].
1451pub async fn any_ok<Ok, Err, F: IntoFuture<Output = Result<Ok, Err>>>(futures: impl IntoIterator<Item = F>) -> Result<Ok, Vec<Err>> {
1452    let mut futures: Vec<_> = futures.into_iter().map(|f| FutureOrOutput::Future(f.into_future())).collect();
1453    future_fn(move |cx| {
1454        let mut pending = false;
1455        for input in &mut futures {
1456            if let FutureOrOutput::Future(fut) = input {
1457                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1458                // Future::poll call, so it will not move.
1459                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1460                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1461                    match r {
1462                        Ok(r) => return Poll::Ready(Ok(r)),
1463                        Err(e) => *input = FutureOrOutput::Output(Err(e)),
1464                    }
1465                } else {
1466                    pending = true;
1467                }
1468            }
1469        }
1470
1471        if pending {
1472            Poll::Pending
1473        } else {
1474            Poll::Ready(Err(futures
1475                .iter_mut()
1476                .map(|f| match f.take_output() {
1477                    Ok(_) => unreachable!(),
1478                    Err(e) => e,
1479                })
1480                .collect()))
1481        }
1482    })
1483    .await
1484}
1485
1486/// <span data-del-macro-root></span> A future that is ready when any of the futures is ready and `Some(T)`.
1487///
1488/// The macro input is comma separated list of future expressions, the futures must
1489/// all have the same output `Option<T>` type. The macro output is a future that when ".awaited" produces
1490/// a single output type instance returned by the first input future that completes with a `Some`.
1491/// If all futures complete with a `None` the output is `None`.
1492///
1493/// At least one input future is required and any number of futures is accepted. For more than
1494/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1495/// some IDEs.
1496///
1497/// If two futures are ready and `Some(T)` at the same time the result of the first future in the input list is used.
1498/// After one future is ready and `Some(T)` the other futures are not polled again and are dropped. After a future
1499/// is ready and `None` it is also not polled again and dropped.
1500///
1501/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1502/// known at compile time, use the [`fn@any_some`] async function to await on all futures in a dynamic list of futures.
1503///
1504/// # Examples
1505///
1506/// Await for the first of three futures to complete with `Some`:
1507///
1508/// ```
1509/// use zng_task as task;
1510/// # task::doc_test(false, async {
1511/// let r = task::any_some!(task::run(async { None::<char> }), task::wait(|| Some('b')), async { None::<char> }).await;
1512///
1513/// assert_eq!(Some('b'), r);
1514/// # });
1515/// ```
1516#[macro_export]
1517macro_rules! any_some {
1518    ($fut0:expr $(,)?) => { $crate::__any_some! { fut0: $fut0; } };
1519    ($fut0:expr, $fut1:expr $(,)?) => {
1520        $crate::__any_some! {
1521            fut0: $fut0;
1522            fut1: $fut1;
1523        }
1524    };
1525    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1526        $crate::__any_some! {
1527            fut0: $fut0;
1528            fut1: $fut1;
1529            fut2: $fut2;
1530        }
1531    };
1532    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1533        $crate::__any_some! {
1534            fut0: $fut0;
1535            fut1: $fut1;
1536            fut2: $fut2;
1537            fut3: $fut3;
1538        }
1539    };
1540    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1541        $crate::__any_some! {
1542            fut0: $fut0;
1543            fut1: $fut1;
1544            fut2: $fut2;
1545            fut3: $fut3;
1546            fut4: $fut4;
1547        }
1548    };
1549    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1550        $crate::__any_some! {
1551            fut0: $fut0;
1552            fut1: $fut1;
1553            fut2: $fut2;
1554            fut3: $fut3;
1555            fut4: $fut4;
1556            fut5: $fut5;
1557        }
1558    };
1559    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1560        $crate::__any_some! {
1561            fut0: $fut0;
1562            fut1: $fut1;
1563            fut2: $fut2;
1564            fut3: $fut3;
1565            fut4: $fut4;
1566            fut5: $fut5;
1567            fut6: $fut6;
1568        }
1569    };
1570    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1571        $crate::__any_some! {
1572            fut0: $fut0;
1573            fut1: $fut1;
1574            fut2: $fut2;
1575            fut3: $fut3;
1576            fut4: $fut4;
1577            fut5: $fut5;
1578            fut6: $fut6;
1579            fut7: $fut7;
1580        }
1581    };
1582    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__any_some; $($fut),+ } }
1583}
1584
1585#[doc(hidden)]
1586#[macro_export]
1587macro_rules! __any_some {
1588    ($($ident:ident: $fut: expr;)+) => {
1589        {
1590            $(let mut $ident = Some(std::future::IntoFuture::into_future($fut));)+
1591            $crate::future_fn(move |cx| {
1592                use std::task::Poll;
1593
1594                let mut pending = false;
1595
1596                $(
1597                    if let Some(fut) = $ident.as_mut() {
1598                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1599                        // Future::poll call, so it will not move.
1600                        let mut fut = unsafe { std::pin::Pin::new_unchecked(fut) };
1601                        if let Poll::Ready(r) = fut.as_mut().poll(cx) {
1602                            if let Some(r) = r {
1603                                return Poll::Ready(Some(r));
1604                            }
1605                            $ident = None;
1606                        } else {
1607                            pending = true;
1608                        }
1609                    }
1610                )+
1611
1612                if pending {
1613                    Poll::Pending
1614                } else {
1615                    Poll::Ready(None)
1616                }
1617            })
1618        }
1619    }
1620}
1621
1622/// A future that awaits on all `futures` at the same time and returns when any future is `Some(_)` or all are `None`.
1623///
1624/// This is the dynamic version of [`all_some!`].
1625pub async fn any_some<Some, F: IntoFuture<Output = Option<Some>>>(futures: impl IntoIterator<Item = F>) -> Option<Some> {
1626    let mut futures: Vec<_> = futures.into_iter().map(|f| Some(f.into_future())).collect();
1627    future_fn(move |cx| {
1628        let mut pending = false;
1629        for input in &mut futures {
1630            if let Some(fut) = input {
1631                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1632                // Future::poll call, so it will not move.
1633                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1634                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1635                    match r {
1636                        Some(r) => return Poll::Ready(Some(r)),
1637                        None => *input = None,
1638                    }
1639                } else {
1640                    pending = true;
1641                }
1642            }
1643        }
1644
1645        if pending { Poll::Pending } else { Poll::Ready(None) }
1646    })
1647    .await
1648}
1649
1650/// <span data-del-macro-root></span> A future that is ready when all futures are ready with an `Ok(T)` result or
1651/// any future is ready with an `Err(E)` result.
1652///
1653/// The output type is `Result<(T0, T1, ..), E>`, the `Ok` type is a tuple with all the `Ok` values, the error
1654/// type is the first error encountered, the input futures must have the same `Err` type but can have different
1655/// `Ok` types.
1656///
1657/// At least one input future is required and any number of futures is accepted. For more than
1658/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1659/// some IDEs.
1660///
1661/// If two futures are ready and `Err(E)` at the same time the result of the first future in the input list is used.
1662/// After one future is ready and `Err(T)` the other futures are not polled again and are dropped. After a future
1663/// is ready it is also not polled again and dropped.
1664///
1665/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1666/// known at compile time, use the [`fn@all_ok`] async function to await on all futures in a dynamic list of futures.
1667///
1668/// # Examples
1669///
1670/// Await for the first of three futures to complete with `Ok(T)`:
1671///
1672/// ```
1673/// use zng_task as task;
1674/// # #[derive(Debug, PartialEq)]
1675/// # struct FooError;
1676/// # task::doc_test(false, async {
1677/// let r = task::all_ok!(
1678///     task::run(async { Ok::<_, FooError>('a') }),
1679///     task::wait(|| Ok::<_, FooError>('b')),
1680///     async { Ok::<_, FooError>('c') }
1681/// )
1682/// .await;
1683///
1684/// assert_eq!(Ok(('a', 'b', 'c')), r);
1685/// # });
1686/// ```
1687///
1688/// And in if any completes with `Err(E)`:
1689///
1690/// ```
1691/// use zng_task as task;
1692/// # #[derive(Debug, PartialEq)]
1693/// # struct FooError;
1694/// # task::doc_test(false, async {
1695/// let r = task::all_ok!(task::run(async { Ok('a') }), task::wait(|| Err::<char, _>(FooError)), async {
1696///     Ok('c')
1697/// })
1698/// .await;
1699///
1700/// assert_eq!(Err(FooError), r);
1701/// # });
1702/// ```
1703#[macro_export]
1704macro_rules! all_ok {
1705    ($fut0:expr $(,)?) => { $crate::__all_ok! { fut0: $fut0; } };
1706    ($fut0:expr, $fut1:expr $(,)?) => {
1707        $crate::__all_ok! {
1708            fut0: $fut0;
1709            fut1: $fut1;
1710        }
1711    };
1712    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1713        $crate::__all_ok! {
1714            fut0: $fut0;
1715            fut1: $fut1;
1716            fut2: $fut2;
1717        }
1718    };
1719    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1720        $crate::__all_ok! {
1721            fut0: $fut0;
1722            fut1: $fut1;
1723            fut2: $fut2;
1724            fut3: $fut3;
1725        }
1726    };
1727    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1728        $crate::__all_ok! {
1729            fut0: $fut0;
1730            fut1: $fut1;
1731            fut2: $fut2;
1732            fut3: $fut3;
1733            fut4: $fut4;
1734        }
1735    };
1736    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1737        $crate::__all_ok! {
1738            fut0: $fut0;
1739            fut1: $fut1;
1740            fut2: $fut2;
1741            fut3: $fut3;
1742            fut4: $fut4;
1743            fut5: $fut5;
1744        }
1745    };
1746    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1747        $crate::__all_ok! {
1748            fut0: $fut0;
1749            fut1: $fut1;
1750            fut2: $fut2;
1751            fut3: $fut3;
1752            fut4: $fut4;
1753            fut5: $fut5;
1754            fut6: $fut6;
1755        }
1756    };
1757    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1758        $crate::__all_ok! {
1759            fut0: $fut0;
1760            fut1: $fut1;
1761            fut2: $fut2;
1762            fut3: $fut3;
1763            fut4: $fut4;
1764            fut5: $fut5;
1765            fut6: $fut6;
1766            fut7: $fut7;
1767        }
1768    };
1769    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__all_ok; $($fut),+ } }
1770}
1771
1772#[doc(hidden)]
1773#[macro_export]
1774macro_rules! __all_ok {
1775    ($($ident:ident: $fut: expr;)+) => {
1776        {
1777            $(let mut $ident = $crate::FutureOrOutput::Future(std::future::IntoFuture::into_future($fut));)+
1778            $crate::future_fn(move |cx| {
1779                use std::task::Poll;
1780
1781                let mut pending = false;
1782
1783                $(
1784                    if let $crate::FutureOrOutput::Future(fut) = &mut $ident {
1785                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1786                        // Future::poll call, so it will not move.
1787                        let mut fut = unsafe { std::pin::Pin::new_unchecked(fut) };
1788                        if let Poll::Ready(r) = fut.as_mut().poll(cx) {
1789                            match r {
1790                                Ok(r) => {
1791                                    $ident = $crate::FutureOrOutput::Output(Ok(r))
1792                                },
1793                                Err(e) => return Poll::Ready(Err(e)),
1794                            }
1795                        } else {
1796                            pending = true;
1797                        }
1798                    }
1799                )+
1800
1801                if pending {
1802                    Poll::Pending
1803                } else {
1804                    Poll::Ready(Ok((
1805                        $($ident.take_output().unwrap()),+
1806                    )))
1807                }
1808            })
1809        }
1810    }
1811}
1812
1813/// A future that awaits on all `futures` at the same time and returns when all futures are `Ok(_)` or any future is `Err(_)`.
1814///
1815/// This is the dynamic version of [`all_ok!`].
1816pub async fn all_ok<Ok, Err, F: IntoFuture<Output = Result<Ok, Err>>>(futures: impl IntoIterator<Item = F>) -> Result<Vec<Ok>, Err> {
1817    let mut futures: Vec<_> = futures.into_iter().map(|f| FutureOrOutput::Future(f.into_future())).collect();
1818    future_fn(move |cx| {
1819        let mut pending = false;
1820        for input in &mut futures {
1821            if let FutureOrOutput::Future(fut) = input {
1822                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1823                // Future::poll call, so it will not move.
1824                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1825                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1826                    match r {
1827                        Ok(r) => *input = FutureOrOutput::Output(Ok(r)),
1828                        Err(e) => return Poll::Ready(Err(e)),
1829                    }
1830                } else {
1831                    pending = true;
1832                }
1833            }
1834        }
1835
1836        if pending {
1837            Poll::Pending
1838        } else {
1839            Poll::Ready(Ok(futures
1840                .iter_mut()
1841                .map(|f| f.take_output().unwrap_or_else(|_| unreachable!()))
1842                .collect()))
1843        }
1844    })
1845    .await
1846}
1847
1848/// <span data-del-macro-root></span> A future that is ready when all futures are ready with `Some(T)` or when any
1849/// is future ready with `None`.
1850///
1851/// The macro input is comma separated list of future expressions, the futures must
1852/// all have the `Option<T>` output type, but each can have a different `T`. The macro output is a future that when ".awaited"
1853/// produces `Some<(T0, T1, ..)>` if all futures where `Some(T)` or `None` if any of the futures where `None`.
1854///
1855/// At least one input future is required and any number of futures is accepted. For more than
1856/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1857/// some IDEs.
1858///
1859/// After one future is ready and `None` the other futures are not polled again and are dropped. After a future
1860/// is ready it is also not polled again and dropped.
1861///
1862/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1863/// known at compile time, use the [`fn@all_some`] async function to await on all futures in a dynamic list of futures.
1864///
1865/// # Examples
1866///
1867/// Await for the first of three futures to complete with `Some`:
1868///
1869/// ```
1870/// use zng_task as task;
1871/// # task::doc_test(false, async {
1872/// let r = task::all_some!(task::run(async { Some('a') }), task::wait(|| Some('b')), async { Some('c') }).await;
1873///
1874/// assert_eq!(Some(('a', 'b', 'c')), r);
1875/// # });
1876/// ```
1877///
1878/// Completes with `None` if any future completes with `None`:
1879///
1880/// ```
1881/// # use zng_task as task;
1882/// # task::doc_test(false, async {
1883/// let r = task::all_some!(task::run(async { Some('a') }), task::wait(|| None::<char>), async { Some('b') }).await;
1884///
1885/// assert_eq!(None, r);
1886/// # });
1887/// ```
1888#[macro_export]
1889macro_rules! all_some {
1890    ($fut0:expr $(,)?) => { $crate::__all_some! { fut0: $fut0; } };
1891    ($fut0:expr, $fut1:expr $(,)?) => {
1892        $crate::__all_some! {
1893            fut0: $fut0;
1894            fut1: $fut1;
1895        }
1896    };
1897    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1898        $crate::__all_some! {
1899            fut0: $fut0;
1900            fut1: $fut1;
1901            fut2: $fut2;
1902        }
1903    };
1904    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1905        $crate::__all_some! {
1906            fut0: $fut0;
1907            fut1: $fut1;
1908            fut2: $fut2;
1909            fut3: $fut3;
1910        }
1911    };
1912    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1913        $crate::__all_some! {
1914            fut0: $fut0;
1915            fut1: $fut1;
1916            fut2: $fut2;
1917            fut3: $fut3;
1918            fut4: $fut4;
1919        }
1920    };
1921    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1922        $crate::__all_some! {
1923            fut0: $fut0;
1924            fut1: $fut1;
1925            fut2: $fut2;
1926            fut3: $fut3;
1927            fut4: $fut4;
1928            fut5: $fut5;
1929        }
1930    };
1931    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1932        $crate::__all_some! {
1933            fut0: $fut0;
1934            fut1: $fut1;
1935            fut2: $fut2;
1936            fut3: $fut3;
1937            fut4: $fut4;
1938            fut5: $fut5;
1939            fut6: $fut6;
1940        }
1941    };
1942    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1943        $crate::__all_some! {
1944            fut0: $fut0;
1945            fut1: $fut1;
1946            fut2: $fut2;
1947            fut3: $fut3;
1948            fut4: $fut4;
1949            fut5: $fut5;
1950            fut6: $fut6;
1951            fut7: $fut7;
1952        }
1953    };
1954    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__all_some; $($fut),+ } }
1955}
1956
1957#[doc(hidden)]
1958#[macro_export]
1959macro_rules! __all_some {
1960    ($($ident:ident: $fut: expr;)+) => {
1961        {
1962            $(let mut $ident = $crate::FutureOrOutput::Future(std::future::IntoFuture::into_future($fut));)+
1963            $crate::future_fn(move |cx| {
1964                use std::task::Poll;
1965
1966                let mut pending = false;
1967
1968                $(
1969                    if let $crate::FutureOrOutput::Future(fut) = &mut $ident {
1970                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1971                        // Future::poll call, so it will not move.
1972                        let mut fut = unsafe { std::pin::Pin::new_unchecked(fut) };
1973                        if let Poll::Ready(r) = fut.as_mut().poll(cx) {
1974                            if r.is_none() {
1975                                return Poll::Ready(None);
1976                            }
1977
1978                            $ident = $crate::FutureOrOutput::Output(r);
1979                        } else {
1980                            pending = true;
1981                        }
1982                    }
1983                )+
1984
1985                if pending {
1986                    Poll::Pending
1987                } else {
1988                    Poll::Ready(Some((
1989                        $($ident.take_output().unwrap()),+
1990                    )))
1991                }
1992            })
1993        }
1994    }
1995}
1996
1997/// A future that awaits on all `futures` at the same time and returns when all futures are `Some(_)` or any future is `None`.
1998///
1999/// This is the dynamic version of [`all_some!`].
2000pub async fn all_some<Some, F: IntoFuture<Output = Option<Some>>>(futures: impl IntoIterator<Item = F>) -> Option<Vec<Some>> {
2001    let mut futures: Vec<_> = futures.into_iter().map(|f| FutureOrOutput::Future(f.into_future())).collect();
2002    future_fn(move |cx| {
2003        let mut pending = false;
2004        for input in &mut futures {
2005            if let FutureOrOutput::Future(fut) = input {
2006                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
2007                // Future::poll call, so it will not move.
2008                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
2009                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
2010                    match r {
2011                        Some(r) => *input = FutureOrOutput::Output(Some(r)),
2012                        None => return Poll::Ready(None),
2013                    }
2014                } else {
2015                    pending = true;
2016                }
2017            }
2018        }
2019
2020        if pending {
2021            Poll::Pending
2022        } else {
2023            Poll::Ready(Some(futures.iter_mut().map(|f| f.take_output().unwrap()).collect()))
2024        }
2025    })
2026    .await
2027}
2028
2029/// A future that will await until [`set`] is called.
2030///
2031/// # Examples
2032///
2033/// Spawns a parallel task that only writes to stdout after the main thread sets the signal:
2034///
2035/// ```
2036/// use zng_clone_move::async_clmv;
2037/// use zng_task::{self as task, *};
2038///
2039/// let signal = SignalOnce::default();
2040///
2041/// task::spawn(async_clmv!(signal, {
2042///     signal.await;
2043///     println!("After Signal!");
2044/// }));
2045///
2046/// signal.set();
2047/// ```
2048///
2049/// [`set`]: SignalOnce::set
2050#[derive(Default, Clone)]
2051pub struct SignalOnce(Arc<SignalInner>);
2052impl fmt::Debug for SignalOnce {
2053    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2054        write!(f, "SignalOnce({})", self.is_set())
2055    }
2056}
2057impl PartialEq for SignalOnce {
2058    fn eq(&self, other: &Self) -> bool {
2059        Arc::ptr_eq(&self.0, &other.0)
2060    }
2061}
2062impl Eq for SignalOnce {}
2063impl Hash for SignalOnce {
2064    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2065        Arc::as_ptr(&self.0).hash(state)
2066    }
2067}
2068impl SignalOnce {
2069    /// New unsigned.
2070    pub fn new() -> Self {
2071        Self::default()
2072    }
2073
2074    /// New signaled.
2075    pub fn new_set() -> Self {
2076        let s = Self::new();
2077        s.set();
2078        s
2079    }
2080
2081    /// If the signal was set.
2082    pub fn is_set(&self) -> bool {
2083        self.0.signaled.load(Ordering::Relaxed)
2084    }
2085
2086    /// Sets the signal and awakes listeners.
2087    pub fn set(&self) {
2088        if !self.0.signaled.swap(true, Ordering::Relaxed) {
2089            let listeners = mem::take(&mut *self.0.listeners.lock());
2090            for listener in listeners {
2091                listener.wake();
2092            }
2093        }
2094    }
2095}
2096impl Future for SignalOnce {
2097    type Output = ();
2098
2099    fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<()> {
2100        if self.0.signaled.load(Ordering::Relaxed) {
2101            return Poll::Ready(());
2102        }
2103
2104        let mut listeners = self.0.listeners.lock();
2105        if self.0.signaled.load(Ordering::Relaxed) {
2106            return Poll::Ready(());
2107        }
2108
2109        let waker = cx.waker();
2110        if !listeners.iter().any(|w| w.will_wake(waker)) {
2111            listeners.push(waker.clone());
2112        }
2113
2114        Poll::Pending
2115    }
2116}
2117
2118#[derive(Default)]
2119struct SignalInner {
2120    signaled: AtomicBool,
2121    listeners: Mutex<Vec<std::task::Waker>>,
2122}
2123
2124/// A [`Waker`] that dispatches a wake call to multiple other wakers.
2125///
2126/// This is useful for sharing one wake source with multiple [`Waker`] clients that may not be all
2127/// known at the moment the first request is made.
2128///  
2129/// [`Waker`]: std::task::Waker
2130#[derive(Clone)]
2131pub struct McWaker(Arc<WakeVec>);
2132
2133#[derive(Default)]
2134struct WakeVec(Mutex<Vec<std::task::Waker>>);
2135impl WakeVec {
2136    fn push(&self, waker: std::task::Waker) -> bool {
2137        let mut v = self.0.lock();
2138
2139        let return_waker = v.is_empty();
2140
2141        v.push(waker);
2142
2143        return_waker
2144    }
2145
2146    fn cancel(&self) {
2147        let mut v = self.0.lock();
2148
2149        debug_assert!(!v.is_empty(), "called cancel on an empty McWaker");
2150
2151        v.clear();
2152    }
2153}
2154impl std::task::Wake for WakeVec {
2155    fn wake(self: Arc<Self>) {
2156        for w in mem::take(&mut *self.0.lock()) {
2157            w.wake();
2158        }
2159    }
2160}
2161impl McWaker {
2162    /// New empty waker.
2163    pub fn empty() -> Self {
2164        Self(Arc::new(WakeVec::default()))
2165    }
2166
2167    /// Register a `waker` to wake once when `self` awakes.
2168    ///
2169    /// Returns `Some(self as waker)` if `self` was previously empty, if `None` is returned [`Poll::Pending`] must
2170    /// be returned, if a waker is returned the shared resource must be polled using the waker, if the shared resource
2171    /// is ready [`cancel`] must be called.
2172    ///
2173    /// [`cancel`]: Self::cancel
2174    pub fn push(&self, waker: std::task::Waker) -> Option<std::task::Waker> {
2175        if self.0.push(waker) { Some(self.0.clone().into()) } else { None }
2176    }
2177
2178    /// Clear current registered wakers.
2179    pub fn cancel(&self) {
2180        self.0.cancel()
2181    }
2182}
2183
2184/// Panic payload, captured by [`std::panic::catch_unwind`].
2185#[non_exhaustive]
2186pub struct TaskPanicError {
2187    /// Panic payload.
2188    pub payload: Box<dyn Any + Send + 'static>,
2189}
2190impl TaskPanicError {
2191    /// New from panic payload.
2192    pub fn new(payload: Box<dyn Any + Send + 'static>) -> Self {
2193        Self { payload }
2194    }
2195
2196    /// Get the panic string if the `payload` is string like.
2197    pub fn panic_str(&self) -> Option<&str> {
2198        extract_panic_message(&self.payload)
2199    }
2200}
2201impl fmt::Debug for TaskPanicError {
2202    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2203        f.debug_struct("TaskPanicError").field("panic_str()", &self.panic_str()).finish()
2204    }
2205}
2206impl fmt::Display for TaskPanicError {
2207    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2208        if let Some(s) = self.panic_str() { f.write_str(s) } else { Ok(()) }
2209    }
2210}
2211impl std::error::Error for TaskPanicError {}
2212
2213type SpawnPanicHandler = Box<dyn FnMut(TaskPanicError) + Send + 'static>;
2214
2215pub(crate) fn extract_panic_message(p: &dyn Any) -> Option<&str> {
2216    if let Some(s) = p.downcast_ref::<&'static str>() {
2217        Some(s)
2218    } else if let Some(s) = p.downcast_ref::<String>() {
2219        Some(s)
2220    } else {
2221        None
2222    }
2223}
2224
2225app_local! {
2226    // Mutex for Sync only
2227    static SPAWN_PANIC_HANDLERS: Option<Mutex<SpawnPanicHandler>> = None;
2228}
2229
2230/// Set a `handler` that is called when spawn tasks panic.
2231///
2232/// On panic the tasks [`spawn`], [`poll_spawn`] and [`spawn_wait`] log an error, notifies the `handler` and otherwise ignores the panic.
2233///
2234/// The handler is set for the process lifetime, only handler can be set per app. The handler is called inside the same [`LocalContext`]
2235/// and thread the task that panicked was called in.
2236///
2237/// ```
2238/// # macro_rules! example { () => {
2239/// task::set_spawn_panic_handler(|p| {
2240///     UPDATES
2241///         .run_hn_once(hn_once!(|_| {
2242///             std::panic::resume_unwind(p.payload);
2243///         }))
2244///         .perm();
2245/// });
2246/// # }}
2247/// ```
2248///
2249/// The example above shows how to set a handler that propagates the panic to the app main thread.
2250///
2251/// # Panics
2252///
2253/// Panics if another handler is already set in the same app.
2254///
2255/// Panics if no app is running in the caller thread.
2256pub fn set_spawn_panic_handler(handler: impl FnMut(TaskPanicError) + Send + 'static) {
2257    let mut h = SPAWN_PANIC_HANDLERS.try_write().expect("a spawn panic handler is already set");
2258    assert!(h.is_none(), "a spawn panic handler is already set");
2259    *h = Some(Mutex::new(Box::new(handler)));
2260}
2261
2262fn on_spawn_panic(p: TaskPanicError) {
2263    if let Some(f) = &mut *SPAWN_PANIC_HANDLERS.write() {
2264        f.get_mut()(p)
2265    }
2266}