async_rs/implementors/
async_global_executor.rs

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