async_rs/implementors/
async_global_executor.rs

1//! async-global-executor implementation of async runtime definition traits
2
3use crate::{Executor, Runtime, RuntimeParts, Task};
4use async_trait::async_trait;
5use std::{
6    future::Future,
7    pin::Pin,
8    task::{Context, Poll},
9};
10
11#[cfg(feature = "async-io")]
12use crate::AsyncIO;
13
14/// Type alias for the async-global-executor runtime
15#[cfg(feature = "async-io")]
16pub type AGERuntime = Runtime<RuntimeParts<AsyncGlobalExecutor, AsyncIO>>;
17
18#[cfg(feature = "async-io")]
19impl AGERuntime {
20    /// Create a new SmolRuntime
21    pub fn async_global_executor() -> Self {
22        Self::new(RuntimeParts::new(AsyncGlobalExecutor, AsyncIO))
23    }
24}
25
26/// Dummy object implementing executor-trait common interfaces on top of async-global-executor
27#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
28pub struct AsyncGlobalExecutor;
29
30struct AGETask<T: Send>(Option<async_global_executor::Task<T>>);
31
32impl Executor for AsyncGlobalExecutor {
33    fn block_on<T, F: Future<Output = T>>(&self, f: F) -> T {
34        async_global_executor::block_on(f)
35    }
36
37    fn spawn<T: Send + 'static>(
38        &self,
39        f: impl Future<Output = T> + Send + 'static,
40    ) -> impl Task<T> {
41        AGETask(Some(async_global_executor::spawn(f)))
42    }
43
44    fn spawn_blocking<F: FnOnce() -> T + Send + 'static, T: Send + 'static>(
45        &self,
46        f: F,
47    ) -> impl Task<T> {
48        AGETask(Some(async_global_executor::spawn_blocking(f)))
49    }
50}
51
52#[async_trait(?Send)]
53impl<T: Send> Task<T> for AGETask<T> {
54    async fn cancel(&mut self) -> Option<T> {
55        self.0.take()?.cancel().await
56    }
57}
58
59impl<T: Send> Drop for AGETask<T> {
60    fn drop(&mut self) {
61        if let Some(task) = self.0.take() {
62            task.detach();
63        }
64    }
65}
66
67impl<T: Send> Future for AGETask<T> {
68    type Output = T;
69
70    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
71        Pin::new(self.0.as_mut().expect("task canceled")).poll(cx)
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn dyn_compat() {
81        struct Test {
82            _executor: Box<dyn Executor>,
83            _task: Box<dyn Task<String>>,
84        }
85
86        let _ = Test {
87            _executor: Box::new(AsyncGlobalExecutor),
88            _task: Box::new(AGETask(None)),
89        };
90    }
91}