executor_core/
async_task.rs1use crate::{Error, Task};
8use core::{
9 future::Future,
10 panic::AssertUnwindSafe,
11 pin::Pin,
12 task::{Context, Poll},
13};
14
15use alloc::boxed::Box;
16pub use async_task::{Runnable, Task as RawTask};
17
18#[cfg(feature = "std")]
19use crate::catch_unwind;
20
21#[cfg(not(feature = "std"))]
22fn catch_unwind<F, R>(f: F) -> Result<R, Error>
23where
24 F: FnOnce() -> R,
25{
26 Ok(f())
29}
30
31pub struct AsyncTask<T>(async_task::Task<T>);
36
37impl<T> AsyncTask<T> {
38 pub async fn result(self) -> Result<T, Box<dyn core::any::Any + Send>> {
40 crate::Task::result(self).await
41 }
42
43 pub async fn cancel(self) {
45 self.0.cancel().await;
46 }
47}
48
49impl<T> core::fmt::Debug for AsyncTask<T> {
50 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51 f.debug_struct("AsyncTask").finish_non_exhaustive()
52 }
53}
54
55impl<T> From<async_task::Task<T>> for AsyncTask<T> {
56 fn from(task: async_task::Task<T>) -> Self {
57 Self(task)
58 }
59}
60
61impl<T> Future for AsyncTask<T> {
62 type Output = T;
63
64 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
65 Pin::new(&mut self.0).poll(cx)
66 }
67}
68
69impl<T> Task<T> for AsyncTask<T> {
70 fn poll_result(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<T, Error>> {
71 match catch_unwind(AssertUnwindSafe(|| Pin::new(&mut self.0).poll(cx))) {
72 Ok(Poll::Ready(value)) => Poll::Ready(Ok(value)),
73 Ok(Poll::Pending) => Poll::Pending,
74 Err(error) => Poll::Ready(Err(error)),
75 }
76 }
77}
78
79pub fn spawn<F, S>(future: F, scheduler: S) -> (Runnable, AsyncTask<F::Output>)
88where
89 F: Future + Send + 'static,
90 F::Output: Send + 'static,
91 S: Fn(Runnable) + Send + Sync + 'static,
92{
93 let (runnable, task) = async_task::spawn(future, scheduler);
94 (runnable, AsyncTask::from(task))
95}
96
97#[cfg(feature = "std")]
104pub fn spawn_local<F, S>(future: F, scheduler: S) -> (Runnable, AsyncTask<F::Output>)
105where
106 F: Future + 'static,
107 S: Fn(Runnable) + Send + Sync + 'static,
108{
109 let (runnable, task) = async_task::spawn_local(future, scheduler);
110 (runnable, AsyncTask::from(task))
111}