blob: 9335f125fc6a4e7801234700b9b9fbef3cc43a54 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
use std::{future::Future, panic::catch_unwind, sync::Arc, thread};
use once_cell::sync::OnceCell;
#[cfg(feature = "smol")]
pub use smol::Executor as SmolEx;
#[cfg(feature = "tokio")]
pub use tokio::runtime::Runtime;
use super::Task;
#[derive(Clone)]
pub struct Executor {
#[cfg(feature = "smol")]
inner: Arc<SmolEx<'static>>,
#[cfg(feature = "tokio")]
inner: Arc<Runtime>,
}
impl Executor {
pub fn spawn<T: Send + 'static>(
&self,
future: impl Future<Output = T> + Send + 'static,
) -> Task<T> {
self.inner.spawn(future).into()
}
}
static GLOBAL_EXECUTOR: OnceCell<Executor> = OnceCell::new();
/// Returns a single-threaded global executor
pub fn global_executor() -> Executor {
#[cfg(feature = "smol")]
fn init_executor() -> Executor {
let ex = smol::Executor::new();
thread::Builder::new()
.name("smol-executor".to_string())
.spawn(|| loop {
catch_unwind(|| {
smol::block_on(global_executor().inner.run(std::future::pending::<()>()))
})
.ok();
})
.expect("cannot spawn executor thread");
// Prevent spawning another thread by running the process driver on this
// thread. see https://github.com/smol-rs/smol/blob/master/src/spawn.rs
ex.spawn(async_process::driver()).detach();
Executor {
inner: Arc::new(ex),
}
}
#[cfg(feature = "tokio")]
fn init_executor() -> Executor {
let ex = Arc::new(tokio::runtime::Runtime::new().expect("cannot build tokio runtime"));
let ex_cloned = ex.clone();
thread::Builder::new()
.name("tokio-executor".to_string())
.spawn(move || {
catch_unwind(|| ex_cloned.block_on(std::future::pending::<()>())).ok();
})
.expect("cannot spawn tokio runtime thread");
Executor { inner: ex }
}
GLOBAL_EXECUTOR.get_or_init(init_executor).clone()
}
#[cfg(feature = "smol")]
impl From<Arc<smol::Executor<'static>>> for Executor {
fn from(ex: Arc<smol::Executor<'static>>) -> Executor {
Executor { inner: ex }
}
}
#[cfg(feature = "tokio")]
impl From<Arc<tokio::runtime::Runtime>> for Executor {
fn from(rt: Arc<tokio::runtime::Runtime>) -> Executor {
Executor { inner: rt }
}
}
#[cfg(feature = "smol")]
impl From<smol::Executor<'static>> for Executor {
fn from(ex: smol::Executor<'static>) -> Executor {
Executor {
inner: Arc::new(ex),
}
}
}
#[cfg(feature = "tokio")]
impl From<tokio::runtime::Runtime> for Executor {
fn from(rt: tokio::runtime::Runtime) -> Executor {
Executor {
inner: Arc::new(rt),
}
}
}
|