async_scoped/
spawner.rs

1//! There you can find traits that are necessary for implementing executor.
2//! They are mostly unsafe, as we can't ensure the executor allows intended manipulations
3//! without causing UB.
4use futures::Future;
5
6pub unsafe trait Spawner<T> {
7    type FutureOutput;
8    type SpawnHandle: Future<Output = Self::FutureOutput> + Send;
9    fn spawn<F: Future<Output = T> + Send + 'static>(&self, f: F) -> Self::SpawnHandle;
10}
11
12pub unsafe trait FuncSpawner<T> {
13    type FutureOutput;
14    type SpawnHandle: Future<Output = Self::FutureOutput> + Send;
15    fn spawn_func<F: FnOnce() -> T + Send + 'static>(&self, f: F) -> Self::SpawnHandle;
16}
17
18pub unsafe trait Blocker {
19    fn block_on<T, F: Future<Output = T>>(&self, f: F) -> T;
20}
21
22#[cfg(feature = "use-async-std")]
23pub mod use_async_std {
24    use super::*;
25    use async_std::task::{block_on, spawn, spawn_blocking, JoinHandle};
26
27    #[derive(Default)]
28    pub struct AsyncStd;
29
30    unsafe impl<T: Send + 'static> Spawner<T> for AsyncStd {
31        type FutureOutput = T;
32        type SpawnHandle = JoinHandle<T>;
33
34        fn spawn<F: Future<Output = T> + Send + 'static>(&self, f: F) -> Self::SpawnHandle {
35            spawn(f)
36        }
37    }
38    unsafe impl<T: Send + 'static> FuncSpawner<T> for AsyncStd {
39        type FutureOutput = T;
40        type SpawnHandle = JoinHandle<T>;
41
42        fn spawn_func<F: FnOnce() -> T + Send + 'static>(&self, f: F) -> Self::SpawnHandle {
43            spawn_blocking(f)
44        }
45    }
46    unsafe impl Blocker for AsyncStd {
47        fn block_on<T, F: Future<Output = T>>(&self, f: F) -> T {
48            block_on(f)
49        }
50    }
51}
52
53#[cfg(feature = "use-tokio")]
54pub mod use_tokio {
55    use super::*;
56    use tokio::task as tokio_task;
57
58    #[derive(Default)]
59    pub struct Tokio;
60
61    unsafe impl<T: Send + 'static> Spawner<T> for Tokio {
62        type FutureOutput = Result<T, tokio_task::JoinError>;
63        type SpawnHandle = tokio_task::JoinHandle<T>;
64
65        fn spawn<F: Future<Output = T> + Send + 'static>(&self, f: F) -> Self::SpawnHandle {
66            tokio_task::spawn(f)
67        }
68    }
69
70    unsafe impl<T: Send + 'static> FuncSpawner<T> for Tokio {
71        type FutureOutput = Result<T, tokio_task::JoinError>;
72        type SpawnHandle = tokio_task::JoinHandle<T>;
73
74        fn spawn_func<F: FnOnce() -> T + Send + 'static>(&self, f: F) -> Self::SpawnHandle {
75            tokio_task::spawn_blocking(f)
76        }
77    }
78
79    unsafe impl Blocker for Tokio {
80        fn block_on<T, F: Future<Output = T>>(&self, f: F) -> T {
81            tokio_task::block_in_place(|| {
82                tokio::runtime::Builder::new_current_thread()
83                    .build()
84                    .unwrap()
85                    .block_on(f)
86            })
87        }
88    }
89}