async_rt/
task.rs

1use crate::global::GlobalExecutor;
2use crate::{
3    AbortableJoinHandle, CommunicationTask, Executor, JoinHandle, UnboundedCommunicationTask,
4};
5use futures::channel::mpsc::{Receiver, UnboundedReceiver};
6use std::future::Future;
7use std::pin::Pin;
8use std::task::{Context, Poll};
9
10const EXECUTOR: GlobalExecutor = GlobalExecutor;
11
12/// Spawns a new asynchronous task in the background, returning a Future [`JoinHandle`] for it.
13pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
14where
15    F: Future + Send + 'static,
16    F::Output: Send + 'static,
17{
18    EXECUTOR.spawn(future)
19}
20
21/// Spawns a new asynchronous task in the background, returning an abortable handle that will cancel the task
22/// once the handle is dropped.
23///
24/// Note: This function is used if the task is expected to run until the handle is dropped. It is recommended to use
25/// [`spawn`] or [`dispatch`] otherwise.
26pub fn spawn_abortable<F>(future: F) -> AbortableJoinHandle<F::Output>
27where
28    F: Future + Send + 'static,
29    F::Output: Send + 'static,
30{
31    EXECUTOR.spawn_abortable(future)
32}
33
34/// Spawns a new asynchronous task in the background without a handle.
35/// Basically the same as [`spawn`].
36pub fn dispatch<F>(future: F)
37where
38    F: Future + Send + 'static,
39    F::Output: Send + 'static,
40{
41    EXECUTOR.dispatch(future);
42}
43
44/// Spawns a new asynchronous task that accepts messages to the task using [`channels`](futures::channel::mpsc).
45/// This function returns a handle that allows sending a message, or if there is no reference to the handle at all
46/// (in other words, all handles are dropped), the task would be aborted.
47pub fn spawn_coroutine<T, F, Fut>(f: F) -> CommunicationTask<T>
48where
49    F: FnMut(Receiver<T>) -> Fut,
50    Fut: Future<Output = ()> + Send + 'static,
51{
52    EXECUTOR.spawn_coroutine(f)
53}
54
55/// Spawns a new asynchronous task with provided context that accepts messages to the task using [`channels`](futures::channel::mpsc).
56/// This function returns a handle that allows sending a message, or if there is no reference to the handle at all
57/// (in other words, all handles are dropped), the task would be aborted.
58pub fn spawn_coroutine_with_context<T, F, C, Fut>(context: C, f: F) -> CommunicationTask<T>
59where
60    F: FnMut(C, Receiver<T>) -> Fut,
61    Fut: Future<Output = ()> + Send + 'static,
62{
63    EXECUTOR.spawn_coroutine_with_context(context, f)
64}
65
66/// Spawns a new asynchronous task that accepts messages to the task using [`channels`](futures::channel::mpsc).
67/// This function returns a handle that allows sending a message, or if there is no reference to the handle at all
68/// (in other words, all handles are dropped), the task would be aborted.
69pub fn spawn_unbounded_coroutine<T, F, Fut>(f: F) -> UnboundedCommunicationTask<T>
70where
71    F: FnMut(UnboundedReceiver<T>) -> Fut,
72    Fut: Future<Output = ()> + Send + 'static,
73{
74    EXECUTOR.spawn_unbounded_coroutine(f)
75}
76
77/// Spawns a new asynchronous task with provided context that accepts messages to the task using [`channels`](futures::channel::mpsc).
78/// This function returns a handle that allows sending a message, or if there is no reference to the handle at all
79/// (in other words, all handles are dropped), the task would be aborted.
80pub fn spawn_unbounded_coroutine_with_context<T, F, C, Fut>(
81    context: C,
82    f: F,
83) -> UnboundedCommunicationTask<T>
84where
85    F: FnMut(C, UnboundedReceiver<T>) -> Fut,
86    Fut: Future<Output = ()> + Send + 'static,
87{
88    EXECUTOR.spawn_unbounded_coroutine_with_context(context, f)
89}
90
91#[derive(Default)]
92struct Yield {
93    yielded: bool,
94}
95
96impl Future for Yield {
97    type Output = ();
98
99    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
100        if self.yielded {
101            return Poll::Ready(());
102        }
103        self.yielded = true;
104        cx.waker().wake_by_ref();
105        Poll::Pending
106    }
107}
108
109/// Yields execution back to the runtime
110pub fn yield_now() -> impl Future<Output = ()> {
111    Yield::default()
112}