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
870pub fn deadline(deadline: impl Into<Deadline>) -> Pin<Box<dyn Future<Output = ()> + Send + Sync>> {
871    let deadline = deadline.into();
872    if zng_app_context::LocalContext::current_app().is_some() {
873        DEADLINE_SV.read().0(deadline)
874    } else {
875        default_deadline(deadline)
876    }
877}
878
879app_local! {
880    static DEADLINE_SV: (DeadlineService, bool) = const { (default_deadline, false) };
881}
882
883type DeadlineService = fn(Deadline) -> Pin<Box<dyn Future<Output = ()> + Send + Sync>>;
884
885fn default_deadline(deadline: Deadline) -> Pin<Box<dyn Future<Output = ()> + Send + Sync>> {
886    if let Some(timeout) = deadline.time_left() {
887        Box::pin(futures_timer::Delay::new(timeout))
888    } else {
889        Box::pin(std::future::ready(()))
890    }
891}
892
893/// Deadline APP integration.
894#[expect(non_camel_case_types)]
895pub struct DEADLINE_APP;
896
897impl DEADLINE_APP {
898    /// Called by the app implementer to setup the [`deadline`] executor.
899    ///
900    /// If no app calls this the [`futures_timer`] executor is used.
901    ///
902    /// [`futures_timer`]: https://docs.rs/futures-timer
903    ///
904    /// # Panics
905    ///
906    /// Panics if called more than once for the same app.
907    pub fn init_deadline_service(&self, service: DeadlineService) {
908        let (prev, already_set) = mem::replace(&mut *DEADLINE_SV.write(), (service, true));
909        if already_set {
910            *DEADLINE_SV.write() = (prev, true);
911            panic!("deadline service already inited for this app");
912        }
913    }
914}
915
916/// Implements a [`Future`] from a closure.
917///
918/// # Examples
919///
920/// A future that is ready with a closure returns `Some(R)`.
921///
922/// ```
923/// use std::task::Poll;
924/// use zng_task as task;
925///
926/// async fn ready_some<R>(mut closure: impl FnMut() -> Option<R>) -> R {
927///     task::future_fn(|cx| match closure() {
928///         Some(r) => Poll::Ready(r),
929///         None => Poll::Pending,
930///     })
931///     .await
932/// }
933/// ```
934pub async fn future_fn<T, F>(fn_: F) -> T
935where
936    F: FnMut(&mut std::task::Context) -> Poll<T>,
937{
938    struct PollFn<F>(F);
939    impl<F> Unpin for PollFn<F> {}
940    impl<T, F: FnMut(&mut std::task::Context<'_>) -> Poll<T>> Future for PollFn<F> {
941        type Output = T;
942
943        fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
944            (self.0)(cx)
945        }
946    }
947    PollFn(fn_).await
948}
949
950/// Error when [`with_deadline`] reach a time limit before a task finishes.
951#[derive(Debug, Clone, Copy)]
952#[non_exhaustive]
953pub struct DeadlineError {}
954impl fmt::Display for DeadlineError {
955    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
956        write!(f, "reached deadline")
957    }
958}
959impl std::error::Error for DeadlineError {}
960
961/// Add a [`deadline`] to a future.
962///
963/// Returns the `fut` output or [`DeadlineError`] if the deadline elapses first.
964pub async fn with_deadline<O, F: Future<Output = O>>(
965    fut: impl IntoFuture<IntoFuture = F>,
966    deadline: impl Into<Deadline>,
967) -> Result<F::Output, DeadlineError> {
968    let deadline = deadline.into();
969    any!(async { Ok(fut.await) }, async {
970        self::deadline(deadline).await;
971        Err(DeadlineError {})
972    })
973    .await
974}
975
976/// <span data-del-macro-root></span> A future that *zips* other futures.
977///
978/// The macro input is a comma separated list of future expressions. The macro output is a future
979/// that when ".awaited" produces a tuple of results in the same order as the inputs.
980///
981/// At least one input future is required and any number of futures is accepted. For more than
982/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
983/// some IDEs.
984///
985/// Each input must implement [`IntoFuture`]. Note that each input must be known at compile time, use the [`fn@all`] async
986/// function to await on all futures in a dynamic list of futures.
987///
988/// # Examples
989///
990/// Await for three different futures to complete:
991///
992/// ```
993/// use zng_task as task;
994///
995/// # task::doc_test(false, async {
996/// let (a, b, c) = task::all!(task::run(async { 'a' }), task::wait(|| "b"), async { b"c" }).await;
997/// # });
998/// ```
999#[macro_export]
1000macro_rules! all {
1001    ($fut0:expr $(,)?) => { $crate::__all! { fut0: $fut0; } };
1002    ($fut0:expr, $fut1:expr $(,)?) => {
1003        $crate::__all! {
1004            fut0: $fut0;
1005            fut1: $fut1;
1006        }
1007    };
1008    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1009        $crate::__all! {
1010            fut0: $fut0;
1011            fut1: $fut1;
1012            fut2: $fut2;
1013        }
1014    };
1015    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1016        $crate::__all! {
1017            fut0: $fut0;
1018            fut1: $fut1;
1019            fut2: $fut2;
1020            fut3: $fut3;
1021        }
1022    };
1023    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1024        $crate::__all! {
1025            fut0: $fut0;
1026            fut1: $fut1;
1027            fut2: $fut2;
1028            fut3: $fut3;
1029            fut4: $fut4;
1030        }
1031    };
1032    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1033        $crate::__all! {
1034            fut0: $fut0;
1035            fut1: $fut1;
1036            fut2: $fut2;
1037            fut3: $fut3;
1038            fut4: $fut4;
1039            fut5: $fut5;
1040        }
1041    };
1042    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1043        $crate::__all! {
1044            fut0: $fut0;
1045            fut1: $fut1;
1046            fut2: $fut2;
1047            fut3: $fut3;
1048            fut4: $fut4;
1049            fut5: $fut5;
1050            fut6: $fut6;
1051        }
1052    };
1053    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1054        $crate::__all! {
1055            fut0: $fut0;
1056            fut1: $fut1;
1057            fut2: $fut2;
1058            fut3: $fut3;
1059            fut4: $fut4;
1060            fut5: $fut5;
1061            fut6: $fut6;
1062            fut7: $fut7;
1063        }
1064    };
1065    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__all; $($fut),+ } }
1066}
1067
1068#[doc(hidden)]
1069#[macro_export]
1070macro_rules! __all {
1071    ($($ident:ident: $fut:expr;)+) => {
1072        {
1073            $(let mut $ident = $crate::FutureOrOutput::Future(std::future::IntoFuture::into_future($fut));)+
1074            $crate::future_fn(move |cx| {
1075                use std::task::Poll;
1076
1077                let mut pending = false;
1078
1079                $(
1080                    if let $crate::FutureOrOutput::Future(fut) = &mut $ident {
1081                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1082                        // Future::poll call, so it will not move.
1083                        let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1084                        if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1085                            $ident = $crate::FutureOrOutput::Output(r);
1086                        } else {
1087                            pending = true;
1088                        }
1089                    }
1090                )+
1091
1092                if pending {
1093                    Poll::Pending
1094                } else {
1095                    Poll::Ready(($($ident.take_output()),+))
1096                }
1097            })
1098        }
1099    }
1100}
1101
1102#[doc(hidden)]
1103pub enum FutureOrOutput<F: Future> {
1104    Future(F),
1105    Output(F::Output),
1106    Taken,
1107}
1108impl<F: Future> FutureOrOutput<F> {
1109    pub fn take_output(&mut self) -> F::Output {
1110        match std::mem::replace(self, Self::Taken) {
1111            FutureOrOutput::Output(o) => o,
1112            _ => unreachable!(),
1113        }
1114    }
1115}
1116
1117/// A future that awaits on all `futures` at the same time and returns all results when all futures are ready.
1118///
1119/// This is the dynamic version of [`all!`].
1120pub async fn all<F: IntoFuture>(futures: impl IntoIterator<Item = F>) -> Vec<F::Output> {
1121    let mut futures: Vec<_> = futures.into_iter().map(|f| FutureOrOutput::Future(f.into_future())).collect();
1122    future_fn(move |cx| {
1123        let mut pending = false;
1124        for input in &mut futures {
1125            if let FutureOrOutput::Future(fut) = input {
1126                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1127                // Future::poll call, so it will not move.
1128                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1129                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1130                    *input = FutureOrOutput::Output(r);
1131                } else {
1132                    pending = true;
1133                }
1134            }
1135        }
1136
1137        if pending {
1138            Poll::Pending
1139        } else {
1140            Poll::Ready(futures.iter_mut().map(FutureOrOutput::take_output).collect())
1141        }
1142    })
1143    .await
1144}
1145
1146/// <span data-del-macro-root></span> A future that awaits for the first future that is ready.
1147///
1148/// The macro input is comma separated list of future expressions, the futures must
1149/// all have the same output type. The macro output is a future that when ".awaited" produces
1150/// a single output type instance returned by the first input future that completes.
1151///
1152/// At least one input future is required and any number of futures is accepted. For more than
1153/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1154/// some IDEs.
1155///
1156/// If two futures are ready at the same time the result of the first future in the input list is used.
1157/// After one future is ready the other futures are not polled again and are dropped.
1158///
1159/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1160/// known at compile time, use the [`fn@any`] async function to await on all futures in a dynamic list of futures.
1161///
1162/// # Examples
1163///
1164/// Await for the first of three futures to complete:
1165///
1166/// ```
1167/// use zng_task as task;
1168/// use zng_unit::*;
1169///
1170/// # task::doc_test(false, async {
1171/// let r = task::any!(
1172///     task::run(async {
1173///         task::deadline(300.ms()).await;
1174///         'a'
1175///     }),
1176///     task::wait(|| 'b'),
1177///     async {
1178///         task::deadline(300.ms()).await;
1179///         'c'
1180///     }
1181/// )
1182/// .await;
1183///
1184/// assert_eq!('b', r);
1185/// # });
1186/// ```
1187#[macro_export]
1188macro_rules! any {
1189    ($fut0:expr $(,)?) => { $crate::__any! { fut0: $fut0; } };
1190    ($fut0:expr, $fut1:expr $(,)?) => {
1191        $crate::__any! {
1192            fut0: $fut0;
1193            fut1: $fut1;
1194        }
1195    };
1196    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1197        $crate::__any! {
1198            fut0: $fut0;
1199            fut1: $fut1;
1200            fut2: $fut2;
1201        }
1202    };
1203    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1204        $crate::__any! {
1205            fut0: $fut0;
1206            fut1: $fut1;
1207            fut2: $fut2;
1208            fut3: $fut3;
1209        }
1210    };
1211    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1212        $crate::__any! {
1213            fut0: $fut0;
1214            fut1: $fut1;
1215            fut2: $fut2;
1216            fut3: $fut3;
1217            fut4: $fut4;
1218        }
1219    };
1220    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1221        $crate::__any! {
1222            fut0: $fut0;
1223            fut1: $fut1;
1224            fut2: $fut2;
1225            fut3: $fut3;
1226            fut4: $fut4;
1227            fut5: $fut5;
1228        }
1229    };
1230    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1231        $crate::__any! {
1232            fut0: $fut0;
1233            fut1: $fut1;
1234            fut2: $fut2;
1235            fut3: $fut3;
1236            fut4: $fut4;
1237            fut5: $fut5;
1238            fut6: $fut6;
1239        }
1240    };
1241    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1242        $crate::__any! {
1243            fut0: $fut0;
1244            fut1: $fut1;
1245            fut2: $fut2;
1246            fut3: $fut3;
1247            fut4: $fut4;
1248            fut5: $fut5;
1249            fut6: $fut6;
1250            fut7: $fut7;
1251        }
1252    };
1253    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__any; $($fut),+ } }
1254}
1255#[doc(hidden)]
1256#[macro_export]
1257macro_rules! __any {
1258    ($($ident:ident: $fut:expr;)+) => {
1259        {
1260            $(let mut $ident = std::future::IntoFuture::into_future($fut);)+
1261            $crate::future_fn(move |cx| {
1262                use std::task::Poll;
1263                $(
1264                    // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1265                    // Future::poll call, so it will not move.
1266                    let mut $ident = unsafe { std::pin::Pin::new_unchecked(&mut $ident) };
1267                    if let Poll::Ready(r) = $ident.as_mut().poll(cx) {
1268                        return Poll::Ready(r)
1269                    }
1270                )+
1271
1272                Poll::Pending
1273            })
1274        }
1275    }
1276}
1277#[doc(hidden)]
1278pub use zng_task_proc_macros::task_any_all as __proc_any_all;
1279
1280/// A future that awaits on all `futures` at the same time and returns the first result when the first future is ready.
1281///
1282/// This is the dynamic version of [`any!`].
1283pub async fn any<F: IntoFuture>(futures: impl IntoIterator<Item = F>) -> F::Output {
1284    let mut futures: Vec<_> = futures.into_iter().map(IntoFuture::into_future).collect();
1285    future_fn(move |cx| {
1286        for fut in &mut futures {
1287            // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1288            // Future::poll call, so it will not move.
1289            let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1290            if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1291                return Poll::Ready(r);
1292            }
1293        }
1294        Poll::Pending
1295    })
1296    .await
1297}
1298
1299/// <span data-del-macro-root></span> A future that waits for the first future that is ready with an `Ok(T)` result.
1300///
1301/// The macro input is comma separated list of future expressions, the futures must
1302/// all have the same output `Result<T, E>` type, but each can have a different `E`. The macro output is a future
1303/// that when ".awaited" produces a single output of type `Result<T, (E0, E1, ..)>` that is `Ok(T)` if any of the futures
1304/// is `Ok(T)` or is `Err((E0, E1, ..))` is all futures are `Err`.
1305///
1306/// At least one input future is required and any number of futures is accepted. For more than
1307/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1308/// some IDEs.
1309///
1310/// If two futures are ready and `Ok(T)` at the same time the result of the first future in the input list is used.
1311/// After one future is ready and `Ok(T)` the other futures are not polled again and are dropped. After a future
1312/// is ready and `Err(E)` it is also not polled again and dropped.
1313///
1314/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1315/// known at compile time, use the [`fn@any_ok`] async function to await on all futures in a dynamic list of futures.
1316///
1317/// # Examples
1318///
1319/// Await for the first of three futures to complete with `Ok`:
1320///
1321/// ```
1322/// use zng_task as task;
1323/// # #[derive(Debug, PartialEq)]
1324/// # pub struct FooError;
1325/// # task::doc_test(false, async {
1326/// let r = task::any_ok!(
1327///     task::run(async { Err::<char, _>("error") }),
1328///     task::wait(|| Ok::<_, FooError>('b')),
1329///     async { Err::<char, _>(FooError) }
1330/// )
1331/// .await;
1332///
1333/// assert_eq!(Ok('b'), r);
1334/// # });
1335/// ```
1336#[macro_export]
1337macro_rules! any_ok {
1338    ($fut0:expr $(,)?) => { $crate::__any_ok! { fut0: $fut0; } };
1339    ($fut0:expr, $fut1:expr $(,)?) => {
1340        $crate::__any_ok! {
1341            fut0: $fut0;
1342            fut1: $fut1;
1343        }
1344    };
1345    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1346        $crate::__any_ok! {
1347            fut0: $fut0;
1348            fut1: $fut1;
1349            fut2: $fut2;
1350        }
1351    };
1352    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1353        $crate::__any_ok! {
1354            fut0: $fut0;
1355            fut1: $fut1;
1356            fut2: $fut2;
1357            fut3: $fut3;
1358        }
1359    };
1360    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1361        $crate::__any_ok! {
1362            fut0: $fut0;
1363            fut1: $fut1;
1364            fut2: $fut2;
1365            fut3: $fut3;
1366            fut4: $fut4;
1367        }
1368    };
1369    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1370        $crate::__any_ok! {
1371            fut0: $fut0;
1372            fut1: $fut1;
1373            fut2: $fut2;
1374            fut3: $fut3;
1375            fut4: $fut4;
1376            fut5: $fut5;
1377        }
1378    };
1379    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1380        $crate::__any_ok! {
1381            fut0: $fut0;
1382            fut1: $fut1;
1383            fut2: $fut2;
1384            fut3: $fut3;
1385            fut4: $fut4;
1386            fut5: $fut5;
1387            fut6: $fut6;
1388        }
1389    };
1390    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1391        $crate::__any_ok! {
1392            fut0: $fut0;
1393            fut1: $fut1;
1394            fut2: $fut2;
1395            fut3: $fut3;
1396            fut4: $fut4;
1397            fut5: $fut5;
1398            fut6: $fut6;
1399            fut7: $fut7;
1400        }
1401    };
1402    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__any_ok; $($fut),+ } }
1403}
1404
1405#[doc(hidden)]
1406#[macro_export]
1407macro_rules! __any_ok {
1408    ($($ident:ident: $fut: expr;)+) => {
1409        {
1410            $(let mut $ident = $crate::FutureOrOutput::Future(std::future::IntoFuture::into_future($fut));)+
1411            $crate::future_fn(move |cx| {
1412                use std::task::Poll;
1413
1414                let mut pending = false;
1415
1416                $(
1417                    if let $crate::FutureOrOutput::Future(fut) = &mut $ident {
1418                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1419                        // Future::poll call, so it will not move.
1420                        let mut fut = unsafe { std::pin::Pin::new_unchecked(fut) };
1421                        if let Poll::Ready(r) = fut.as_mut().poll(cx) {
1422                            match r {
1423                                Ok(r) => return Poll::Ready(Ok(r)),
1424                                Err(e) => {
1425                                    $ident = $crate::FutureOrOutput::Output(Err(e));
1426                                }
1427                            }
1428                        } else {
1429                            pending = true;
1430                        }
1431                    }
1432                )+
1433
1434                if pending {
1435                    Poll::Pending
1436                } else {
1437                    Poll::Ready(Err((
1438                        $($ident.take_output().unwrap_err()),+
1439                    )))
1440                }
1441            })
1442        }
1443    }
1444}
1445
1446/// A future that awaits on all `futures` at the same time and returns when any future is `Ok(_)` or all are `Err(_)`.
1447///
1448/// This is the dynamic version of [`all_some!`].
1449pub async fn any_ok<Ok, Err, F: IntoFuture<Output = Result<Ok, Err>>>(futures: impl IntoIterator<Item = F>) -> Result<Ok, Vec<Err>> {
1450    let mut futures: Vec<_> = futures.into_iter().map(|f| FutureOrOutput::Future(f.into_future())).collect();
1451    future_fn(move |cx| {
1452        let mut pending = false;
1453        for input in &mut futures {
1454            if let FutureOrOutput::Future(fut) = input {
1455                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1456                // Future::poll call, so it will not move.
1457                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1458                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1459                    match r {
1460                        Ok(r) => return Poll::Ready(Ok(r)),
1461                        Err(e) => *input = FutureOrOutput::Output(Err(e)),
1462                    }
1463                } else {
1464                    pending = true;
1465                }
1466            }
1467        }
1468
1469        if pending {
1470            Poll::Pending
1471        } else {
1472            Poll::Ready(Err(futures
1473                .iter_mut()
1474                .map(|f| match f.take_output() {
1475                    Ok(_) => unreachable!(),
1476                    Err(e) => e,
1477                })
1478                .collect()))
1479        }
1480    })
1481    .await
1482}
1483
1484/// <span data-del-macro-root></span> A future that is ready when any of the futures is ready and `Some(T)`.
1485///
1486/// The macro input is comma separated list of future expressions, the futures must
1487/// all have the same output `Option<T>` type. The macro output is a future that when ".awaited" produces
1488/// a single output type instance returned by the first input future that completes with a `Some`.
1489/// If all futures complete with a `None` the output is `None`.
1490///
1491/// At least one input future is required and any number of futures is accepted. For more than
1492/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1493/// some IDEs.
1494///
1495/// If two futures are ready and `Some(T)` at the same time the result of the first future in the input list is used.
1496/// After one future is ready and `Some(T)` the other futures are not polled again and are dropped. After a future
1497/// is ready and `None` it is also not polled again and dropped.
1498///
1499/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1500/// known at compile time, use the [`fn@any_some`] async function to await on all futures in a dynamic list of futures.
1501///
1502/// # Examples
1503///
1504/// Await for the first of three futures to complete with `Some`:
1505///
1506/// ```
1507/// use zng_task as task;
1508/// # task::doc_test(false, async {
1509/// let r = task::any_some!(task::run(async { None::<char> }), task::wait(|| Some('b')), async { None::<char> }).await;
1510///
1511/// assert_eq!(Some('b'), r);
1512/// # });
1513/// ```
1514#[macro_export]
1515macro_rules! any_some {
1516    ($fut0:expr $(,)?) => { $crate::__any_some! { fut0: $fut0; } };
1517    ($fut0:expr, $fut1:expr $(,)?) => {
1518        $crate::__any_some! {
1519            fut0: $fut0;
1520            fut1: $fut1;
1521        }
1522    };
1523    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1524        $crate::__any_some! {
1525            fut0: $fut0;
1526            fut1: $fut1;
1527            fut2: $fut2;
1528        }
1529    };
1530    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1531        $crate::__any_some! {
1532            fut0: $fut0;
1533            fut1: $fut1;
1534            fut2: $fut2;
1535            fut3: $fut3;
1536        }
1537    };
1538    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1539        $crate::__any_some! {
1540            fut0: $fut0;
1541            fut1: $fut1;
1542            fut2: $fut2;
1543            fut3: $fut3;
1544            fut4: $fut4;
1545        }
1546    };
1547    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1548        $crate::__any_some! {
1549            fut0: $fut0;
1550            fut1: $fut1;
1551            fut2: $fut2;
1552            fut3: $fut3;
1553            fut4: $fut4;
1554            fut5: $fut5;
1555        }
1556    };
1557    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1558        $crate::__any_some! {
1559            fut0: $fut0;
1560            fut1: $fut1;
1561            fut2: $fut2;
1562            fut3: $fut3;
1563            fut4: $fut4;
1564            fut5: $fut5;
1565            fut6: $fut6;
1566        }
1567    };
1568    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1569        $crate::__any_some! {
1570            fut0: $fut0;
1571            fut1: $fut1;
1572            fut2: $fut2;
1573            fut3: $fut3;
1574            fut4: $fut4;
1575            fut5: $fut5;
1576            fut6: $fut6;
1577            fut7: $fut7;
1578        }
1579    };
1580    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__any_some; $($fut),+ } }
1581}
1582
1583#[doc(hidden)]
1584#[macro_export]
1585macro_rules! __any_some {
1586    ($($ident:ident: $fut: expr;)+) => {
1587        {
1588            $(let mut $ident = Some(std::future::IntoFuture::into_future($fut));)+
1589            $crate::future_fn(move |cx| {
1590                use std::task::Poll;
1591
1592                let mut pending = false;
1593
1594                $(
1595                    if let Some(fut) = $ident.as_mut() {
1596                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1597                        // Future::poll call, so it will not move.
1598                        let mut fut = unsafe { std::pin::Pin::new_unchecked(fut) };
1599                        if let Poll::Ready(r) = fut.as_mut().poll(cx) {
1600                            if let Some(r) = r {
1601                                return Poll::Ready(Some(r));
1602                            }
1603                            $ident = None;
1604                        } else {
1605                            pending = true;
1606                        }
1607                    }
1608                )+
1609
1610                if pending {
1611                    Poll::Pending
1612                } else {
1613                    Poll::Ready(None)
1614                }
1615            })
1616        }
1617    }
1618}
1619
1620/// A future that awaits on all `futures` at the same time and returns when any future is `Some(_)` or all are `None`.
1621///
1622/// This is the dynamic version of [`all_some!`].
1623pub async fn any_some<Some, F: IntoFuture<Output = Option<Some>>>(futures: impl IntoIterator<Item = F>) -> Option<Some> {
1624    let mut futures: Vec<_> = futures.into_iter().map(|f| Some(f.into_future())).collect();
1625    future_fn(move |cx| {
1626        let mut pending = false;
1627        for input in &mut futures {
1628            if let Some(fut) = input {
1629                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1630                // Future::poll call, so it will not move.
1631                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1632                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1633                    match r {
1634                        Some(r) => return Poll::Ready(Some(r)),
1635                        None => *input = None,
1636                    }
1637                } else {
1638                    pending = true;
1639                }
1640            }
1641        }
1642
1643        if pending { Poll::Pending } else { Poll::Ready(None) }
1644    })
1645    .await
1646}
1647
1648/// <span data-del-macro-root></span> A future that is ready when all futures are ready with an `Ok(T)` result or
1649/// any future is ready with an `Err(E)` result.
1650///
1651/// The output type is `Result<(T0, T1, ..), E>`, the `Ok` type is a tuple with all the `Ok` values, the error
1652/// type is the first error encountered, the input futures must have the same `Err` type but can have different
1653/// `Ok` types.
1654///
1655/// At least one input future is required and any number of futures is accepted. For more than
1656/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1657/// some IDEs.
1658///
1659/// If two futures are ready and `Err(E)` at the same time the result of the first future in the input list is used.
1660/// After one future is ready and `Err(T)` the other futures are not polled again and are dropped. After a future
1661/// is ready it is also not polled again and dropped.
1662///
1663/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1664/// known at compile time, use the [`fn@all_ok`] async function to await on all futures in a dynamic list of futures.
1665///
1666/// # Examples
1667///
1668/// Await for the first of three futures to complete with `Ok(T)`:
1669///
1670/// ```
1671/// use zng_task as task;
1672/// # #[derive(Debug, PartialEq)]
1673/// # struct FooError;
1674/// # task::doc_test(false, async {
1675/// let r = task::all_ok!(
1676///     task::run(async { Ok::<_, FooError>('a') }),
1677///     task::wait(|| Ok::<_, FooError>('b')),
1678///     async { Ok::<_, FooError>('c') }
1679/// )
1680/// .await;
1681///
1682/// assert_eq!(Ok(('a', 'b', 'c')), r);
1683/// # });
1684/// ```
1685///
1686/// And in if any completes with `Err(E)`:
1687///
1688/// ```
1689/// use zng_task as task;
1690/// # #[derive(Debug, PartialEq)]
1691/// # struct FooError;
1692/// # task::doc_test(false, async {
1693/// let r = task::all_ok!(task::run(async { Ok('a') }), task::wait(|| Err::<char, _>(FooError)), async {
1694///     Ok('c')
1695/// })
1696/// .await;
1697///
1698/// assert_eq!(Err(FooError), r);
1699/// # });
1700/// ```
1701#[macro_export]
1702macro_rules! all_ok {
1703    ($fut0:expr $(,)?) => { $crate::__all_ok! { fut0: $fut0; } };
1704    ($fut0:expr, $fut1:expr $(,)?) => {
1705        $crate::__all_ok! {
1706            fut0: $fut0;
1707            fut1: $fut1;
1708        }
1709    };
1710    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1711        $crate::__all_ok! {
1712            fut0: $fut0;
1713            fut1: $fut1;
1714            fut2: $fut2;
1715        }
1716    };
1717    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1718        $crate::__all_ok! {
1719            fut0: $fut0;
1720            fut1: $fut1;
1721            fut2: $fut2;
1722            fut3: $fut3;
1723        }
1724    };
1725    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1726        $crate::__all_ok! {
1727            fut0: $fut0;
1728            fut1: $fut1;
1729            fut2: $fut2;
1730            fut3: $fut3;
1731            fut4: $fut4;
1732        }
1733    };
1734    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1735        $crate::__all_ok! {
1736            fut0: $fut0;
1737            fut1: $fut1;
1738            fut2: $fut2;
1739            fut3: $fut3;
1740            fut4: $fut4;
1741            fut5: $fut5;
1742        }
1743    };
1744    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1745        $crate::__all_ok! {
1746            fut0: $fut0;
1747            fut1: $fut1;
1748            fut2: $fut2;
1749            fut3: $fut3;
1750            fut4: $fut4;
1751            fut5: $fut5;
1752            fut6: $fut6;
1753        }
1754    };
1755    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1756        $crate::__all_ok! {
1757            fut0: $fut0;
1758            fut1: $fut1;
1759            fut2: $fut2;
1760            fut3: $fut3;
1761            fut4: $fut4;
1762            fut5: $fut5;
1763            fut6: $fut6;
1764            fut7: $fut7;
1765        }
1766    };
1767    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__all_ok; $($fut),+ } }
1768}
1769
1770#[doc(hidden)]
1771#[macro_export]
1772macro_rules! __all_ok {
1773    ($($ident:ident: $fut: expr;)+) => {
1774        {
1775            $(let mut $ident = $crate::FutureOrOutput::Future(std::future::IntoFuture::into_future($fut));)+
1776            $crate::future_fn(move |cx| {
1777                use std::task::Poll;
1778
1779                let mut pending = false;
1780
1781                $(
1782                    if let $crate::FutureOrOutput::Future(fut) = &mut $ident {
1783                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1784                        // Future::poll call, so it will not move.
1785                        let mut fut = unsafe { std::pin::Pin::new_unchecked(fut) };
1786                        if let Poll::Ready(r) = fut.as_mut().poll(cx) {
1787                            match r {
1788                                Ok(r) => {
1789                                    $ident = $crate::FutureOrOutput::Output(Ok(r))
1790                                },
1791                                Err(e) => return Poll::Ready(Err(e)),
1792                            }
1793                        } else {
1794                            pending = true;
1795                        }
1796                    }
1797                )+
1798
1799                if pending {
1800                    Poll::Pending
1801                } else {
1802                    Poll::Ready(Ok((
1803                        $($ident.take_output().unwrap()),+
1804                    )))
1805                }
1806            })
1807        }
1808    }
1809}
1810
1811/// A future that awaits on all `futures` at the same time and returns when all futures are `Ok(_)` or any future is `Err(_)`.
1812///
1813/// This is the dynamic version of [`all_ok!`].
1814pub async fn all_ok<Ok, Err, F: IntoFuture<Output = Result<Ok, Err>>>(futures: impl IntoIterator<Item = F>) -> Result<Vec<Ok>, Err> {
1815    let mut futures: Vec<_> = futures.into_iter().map(|f| FutureOrOutput::Future(f.into_future())).collect();
1816    future_fn(move |cx| {
1817        let mut pending = false;
1818        for input in &mut futures {
1819            if let FutureOrOutput::Future(fut) = input {
1820                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1821                // Future::poll call, so it will not move.
1822                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
1823                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
1824                    match r {
1825                        Ok(r) => *input = FutureOrOutput::Output(Ok(r)),
1826                        Err(e) => return Poll::Ready(Err(e)),
1827                    }
1828                } else {
1829                    pending = true;
1830                }
1831            }
1832        }
1833
1834        if pending {
1835            Poll::Pending
1836        } else {
1837            Poll::Ready(Ok(futures
1838                .iter_mut()
1839                .map(|f| f.take_output().unwrap_or_else(|_| unreachable!()))
1840                .collect()))
1841        }
1842    })
1843    .await
1844}
1845
1846/// <span data-del-macro-root></span> A future that is ready when all futures are ready with `Some(T)` or when any
1847/// is future ready with `None`.
1848///
1849/// The macro input is comma separated list of future expressions, the futures must
1850/// all have the `Option<T>` output type, but each can have a different `T`. The macro output is a future that when ".awaited"
1851/// produces `Some<(T0, T1, ..)>` if all futures where `Some(T)` or `None` if any of the futures where `None`.
1852///
1853/// At least one input future is required and any number of futures is accepted. For more than
1854/// eight futures a proc-macro is used which may cause code auto-complete to stop working in
1855/// some IDEs.
1856///
1857/// After one future is ready and `None` the other futures are not polled again and are dropped. After a future
1858/// is ready it is also not polled again and dropped.
1859///
1860/// Each input must implement [`IntoFuture`] with the same `Output` type. Note that each input must be
1861/// known at compile time, use the [`fn@all_some`] async function to await on all futures in a dynamic list of futures.
1862///
1863/// # Examples
1864///
1865/// Await for the first of three futures to complete with `Some`:
1866///
1867/// ```
1868/// use zng_task as task;
1869/// # task::doc_test(false, async {
1870/// let r = task::all_some!(task::run(async { Some('a') }), task::wait(|| Some('b')), async { Some('c') }).await;
1871///
1872/// assert_eq!(Some(('a', 'b', 'c')), r);
1873/// # });
1874/// ```
1875///
1876/// Completes with `None` if any future completes with `None`:
1877///
1878/// ```
1879/// # use zng_task as task;
1880/// # task::doc_test(false, async {
1881/// let r = task::all_some!(task::run(async { Some('a') }), task::wait(|| None::<char>), async { Some('b') }).await;
1882///
1883/// assert_eq!(None, r);
1884/// # });
1885/// ```
1886#[macro_export]
1887macro_rules! all_some {
1888    ($fut0:expr $(,)?) => { $crate::__all_some! { fut0: $fut0; } };
1889    ($fut0:expr, $fut1:expr $(,)?) => {
1890        $crate::__all_some! {
1891            fut0: $fut0;
1892            fut1: $fut1;
1893        }
1894    };
1895    ($fut0:expr, $fut1:expr, $fut2:expr $(,)?) => {
1896        $crate::__all_some! {
1897            fut0: $fut0;
1898            fut1: $fut1;
1899            fut2: $fut2;
1900        }
1901    };
1902    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr $(,)?) => {
1903        $crate::__all_some! {
1904            fut0: $fut0;
1905            fut1: $fut1;
1906            fut2: $fut2;
1907            fut3: $fut3;
1908        }
1909    };
1910    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr $(,)?) => {
1911        $crate::__all_some! {
1912            fut0: $fut0;
1913            fut1: $fut1;
1914            fut2: $fut2;
1915            fut3: $fut3;
1916            fut4: $fut4;
1917        }
1918    };
1919    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr $(,)?) => {
1920        $crate::__all_some! {
1921            fut0: $fut0;
1922            fut1: $fut1;
1923            fut2: $fut2;
1924            fut3: $fut3;
1925            fut4: $fut4;
1926            fut5: $fut5;
1927        }
1928    };
1929    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr $(,)?) => {
1930        $crate::__all_some! {
1931            fut0: $fut0;
1932            fut1: $fut1;
1933            fut2: $fut2;
1934            fut3: $fut3;
1935            fut4: $fut4;
1936            fut5: $fut5;
1937            fut6: $fut6;
1938        }
1939    };
1940    ($fut0:expr, $fut1:expr, $fut2:expr, $fut3:expr, $fut4:expr, $fut5:expr, $fut6:expr, $fut7:expr $(,)?) => {
1941        $crate::__all_some! {
1942            fut0: $fut0;
1943            fut1: $fut1;
1944            fut2: $fut2;
1945            fut3: $fut3;
1946            fut4: $fut4;
1947            fut5: $fut5;
1948            fut6: $fut6;
1949            fut7: $fut7;
1950        }
1951    };
1952    ($($fut:expr),+ $(,)?) => { $crate::__proc_any_all!{ $crate::__all_some; $($fut),+ } }
1953}
1954
1955#[doc(hidden)]
1956#[macro_export]
1957macro_rules! __all_some {
1958    ($($ident:ident: $fut: expr;)+) => {
1959        {
1960            $(let mut $ident = $crate::FutureOrOutput::Future(std::future::IntoFuture::into_future($fut));)+
1961            $crate::future_fn(move |cx| {
1962                use std::task::Poll;
1963
1964                let mut pending = false;
1965
1966                $(
1967                    if let $crate::FutureOrOutput::Future(fut) = &mut $ident {
1968                        // SAFETY: the closure owns $ident and is an exclusive borrow inside a
1969                        // Future::poll call, so it will not move.
1970                        let mut fut = unsafe { std::pin::Pin::new_unchecked(fut) };
1971                        if let Poll::Ready(r) = fut.as_mut().poll(cx) {
1972                            if r.is_none() {
1973                                return Poll::Ready(None);
1974                            }
1975
1976                            $ident = $crate::FutureOrOutput::Output(r);
1977                        } else {
1978                            pending = true;
1979                        }
1980                    }
1981                )+
1982
1983                if pending {
1984                    Poll::Pending
1985                } else {
1986                    Poll::Ready(Some((
1987                        $($ident.take_output().unwrap()),+
1988                    )))
1989                }
1990            })
1991        }
1992    }
1993}
1994
1995/// A future that awaits on all `futures` at the same time and returns when all futures are `Some(_)` or any future is `None`.
1996///
1997/// This is the dynamic version of [`all_some!`].
1998pub async fn all_some<Some, F: IntoFuture<Output = Option<Some>>>(futures: impl IntoIterator<Item = F>) -> Option<Vec<Some>> {
1999    let mut futures: Vec<_> = futures.into_iter().map(|f| FutureOrOutput::Future(f.into_future())).collect();
2000    future_fn(move |cx| {
2001        let mut pending = false;
2002        for input in &mut futures {
2003            if let FutureOrOutput::Future(fut) = input {
2004                // SAFETY: the closure owns $ident and is an exclusive borrow inside a
2005                // Future::poll call, so it will not move.
2006                let mut fut_mut = unsafe { std::pin::Pin::new_unchecked(fut) };
2007                if let Poll::Ready(r) = fut_mut.as_mut().poll(cx) {
2008                    match r {
2009                        Some(r) => *input = FutureOrOutput::Output(Some(r)),
2010                        None => return Poll::Ready(None),
2011                    }
2012                } else {
2013                    pending = true;
2014                }
2015            }
2016        }
2017
2018        if pending {
2019            Poll::Pending
2020        } else {
2021            Poll::Ready(Some(futures.iter_mut().map(|f| f.take_output().unwrap()).collect()))
2022        }
2023    })
2024    .await
2025}
2026
2027/// A future that will await until [`set`] is called.
2028///
2029/// # Examples
2030///
2031/// Spawns a parallel task that only writes to stdout after the main thread sets the signal:
2032///
2033/// ```
2034/// use zng_clone_move::async_clmv;
2035/// use zng_task::{self as task, *};
2036///
2037/// let signal = SignalOnce::default();
2038///
2039/// task::spawn(async_clmv!(signal, {
2040///     signal.await;
2041///     println!("After Signal!");
2042/// }));
2043///
2044/// signal.set();
2045/// ```
2046///
2047/// [`set`]: SignalOnce::set
2048#[derive(Default, Clone)]
2049pub struct SignalOnce(Arc<SignalInner>);
2050impl fmt::Debug for SignalOnce {
2051    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2052        write!(f, "SignalOnce({})", self.is_set())
2053    }
2054}
2055impl PartialEq for SignalOnce {
2056    fn eq(&self, other: &Self) -> bool {
2057        Arc::ptr_eq(&self.0, &other.0)
2058    }
2059}
2060impl Eq for SignalOnce {}
2061impl Hash for SignalOnce {
2062    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2063        Arc::as_ptr(&self.0).hash(state)
2064    }
2065}
2066impl SignalOnce {
2067    /// New unsigned.
2068    pub fn new() -> Self {
2069        Self::default()
2070    }
2071
2072    /// New signaled.
2073    pub fn new_set() -> Self {
2074        let s = Self::new();
2075        s.set();
2076        s
2077    }
2078
2079    /// If the signal was set.
2080    pub fn is_set(&self) -> bool {
2081        self.0.signaled.load(Ordering::Relaxed)
2082    }
2083
2084    /// Sets the signal and awakes listeners.
2085    pub fn set(&self) {
2086        if !self.0.signaled.swap(true, Ordering::Relaxed) {
2087            let listeners = mem::take(&mut *self.0.listeners.lock());
2088            for listener in listeners {
2089                listener.wake();
2090            }
2091        }
2092    }
2093}
2094impl Future for SignalOnce {
2095    type Output = ();
2096
2097    fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<()> {
2098        if self.0.signaled.load(Ordering::Relaxed) {
2099            return Poll::Ready(());
2100        }
2101
2102        let mut listeners = self.0.listeners.lock();
2103        if self.0.signaled.load(Ordering::Relaxed) {
2104            return Poll::Ready(());
2105        }
2106
2107        let waker = cx.waker();
2108        if !listeners.iter().any(|w| w.will_wake(waker)) {
2109            listeners.push(waker.clone());
2110        }
2111
2112        Poll::Pending
2113    }
2114}
2115
2116#[derive(Default)]
2117struct SignalInner {
2118    signaled: AtomicBool,
2119    listeners: Mutex<Vec<std::task::Waker>>,
2120}
2121
2122/// A [`Waker`] that dispatches a wake call to multiple other wakers.
2123///
2124/// This is useful for sharing one wake source with multiple [`Waker`] clients that may not be all
2125/// known at the moment the first request is made.
2126///  
2127/// [`Waker`]: std::task::Waker
2128#[derive(Clone)]
2129pub struct McWaker(Arc<WakeVec>);
2130
2131#[derive(Default)]
2132struct WakeVec(Mutex<Vec<std::task::Waker>>);
2133impl WakeVec {
2134    fn push(&self, waker: std::task::Waker) -> bool {
2135        let mut v = self.0.lock();
2136
2137        let return_waker = v.is_empty();
2138
2139        v.push(waker);
2140
2141        return_waker
2142    }
2143
2144    fn cancel(&self) {
2145        let mut v = self.0.lock();
2146
2147        debug_assert!(!v.is_empty(), "called cancel on an empty McWaker");
2148
2149        v.clear();
2150    }
2151}
2152impl std::task::Wake for WakeVec {
2153    fn wake(self: Arc<Self>) {
2154        for w in mem::take(&mut *self.0.lock()) {
2155            w.wake();
2156        }
2157    }
2158}
2159impl McWaker {
2160    /// New empty waker.
2161    pub fn empty() -> Self {
2162        Self(Arc::new(WakeVec::default()))
2163    }
2164
2165    /// Register a `waker` to wake once when `self` awakes.
2166    ///
2167    /// Returns `Some(self as waker)` if `self` was previously empty, if `None` is returned [`Poll::Pending`] must
2168    /// be returned, if a waker is returned the shared resource must be polled using the waker, if the shared resource
2169    /// is ready [`cancel`] must be called.
2170    ///
2171    /// [`cancel`]: Self::cancel
2172    pub fn push(&self, waker: std::task::Waker) -> Option<std::task::Waker> {
2173        if self.0.push(waker) { Some(self.0.clone().into()) } else { None }
2174    }
2175
2176    /// Clear current registered wakers.
2177    pub fn cancel(&self) {
2178        self.0.cancel()
2179    }
2180}
2181
2182/// Panic payload, captured by [`std::panic::catch_unwind`].
2183#[non_exhaustive]
2184pub struct TaskPanicError {
2185    /// Panic payload.
2186    pub payload: Box<dyn Any + Send + 'static>,
2187}
2188impl TaskPanicError {
2189    /// New from panic payload.
2190    pub fn new(payload: Box<dyn Any + Send + 'static>) -> Self {
2191        Self { payload }
2192    }
2193
2194    /// Get the panic string if the `payload` is string like.
2195    pub fn panic_str(&self) -> Option<&str> {
2196        extract_panic_message(&self.payload)
2197    }
2198}
2199impl fmt::Debug for TaskPanicError {
2200    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2201        f.debug_struct("TaskPanicError").field("panic_str()", &self.panic_str()).finish()
2202    }
2203}
2204impl fmt::Display for TaskPanicError {
2205    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2206        if let Some(s) = self.panic_str() { f.write_str(s) } else { Ok(()) }
2207    }
2208}
2209impl std::error::Error for TaskPanicError {}
2210
2211type SpawnPanicHandler = Box<dyn FnMut(TaskPanicError) + Send + 'static>;
2212
2213pub(crate) fn extract_panic_message(p: &dyn Any) -> Option<&str> {
2214    if let Some(s) = p.downcast_ref::<&'static str>() {
2215        Some(s)
2216    } else if let Some(s) = p.downcast_ref::<String>() {
2217        Some(s)
2218    } else {
2219        None
2220    }
2221}
2222
2223app_local! {
2224    // Mutex for Sync only
2225    static SPAWN_PANIC_HANDLERS: Option<Mutex<SpawnPanicHandler>> = None;
2226}
2227
2228/// Set a `handler` that is called when spawn tasks panic.
2229///
2230/// On panic the tasks [`spawn`], [`poll_spawn`] and [`spawn_wait`] log an error, notifies the `handler` and otherwise ignores the panic.
2231///
2232/// The handler is set for the process lifetime, only handler can be set per app. The handler is called inside the same [`LocalContext`]
2233/// and thread the task that panicked was called in.
2234///
2235/// ```
2236/// # macro_rules! example { () => {
2237/// task::set_spawn_panic_handler(|p| {
2238///     UPDATES
2239///         .run_hn_once(hn_once!(|_| {
2240///             std::panic::resume_unwind(p.payload);
2241///         }))
2242///         .perm();
2243/// });
2244/// # }}
2245/// ```
2246///
2247/// The example above shows how to set a handler that propagates the panic to the app main thread.
2248///
2249/// # Panics
2250///
2251/// Panics if another handler is already set in the same app.
2252///
2253/// Panics if no app is running in the caller thread.
2254pub fn set_spawn_panic_handler(handler: impl FnMut(TaskPanicError) + Send + 'static) {
2255    let mut h = SPAWN_PANIC_HANDLERS.try_write().expect("a spawn panic handler is already set");
2256    assert!(h.is_none(), "a spawn panic handler is already set");
2257    *h = Some(Mutex::new(Box::new(handler)));
2258}
2259
2260fn on_spawn_panic(p: TaskPanicError) {
2261    if let Some(f) = &mut *SPAWN_PANIC_HANDLERS.write() {
2262        f.get_mut()(p)
2263    }
2264}