Skip to content

Commit 7260e60

Browse files
committed
add tokio02 feature
Signed-off-by: Marc-Antoine Perennou <[email protected]>
1 parent e0bc2ae commit 7260e60

File tree

2 files changed

+47
-5
lines changed

2 files changed

+47
-5
lines changed

Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ readme = "README.md"
1414

1515
[features]
1616
default = ["async-io"]
17+
tokio02 = ["tokio"]
1718

1819
[dependencies]
1920
async-executor = "^1.3"
@@ -25,5 +26,11 @@ once_cell = "^1.4"
2526
version = "^1.0"
2627
optional = true
2728

29+
[dependencies.tokio]
30+
version = "^0.2"
31+
default-features = false
32+
features = ["rt-threaded"]
33+
optional = true
34+
2835
[dev-dependencies]
2936
doc-comment = "^0.3"

src/lib.rs

+40-5
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,12 @@ pub fn init_with_config(config: GlobalExecutorConfig) {
129129
use future::block_on;
130130
loop {
131131
let _ = std::panic::catch_unwind(|| {
132-
LOCAL_EXECUTOR.with(|executor| {
133-
let local = executor.run(future::pending::<()>());
134-
let global = GLOBAL_EXECUTOR.run(future::pending::<()>());
135-
block_on(future::or(local, global))
132+
enter02(|| {
133+
LOCAL_EXECUTOR.with(|executor| {
134+
let local = executor.run(future::pending::<()>());
135+
let global = GLOBAL_EXECUTOR.run(future::pending::<()>());
136+
block_on(future::or(local, global))
137+
})
136138
})
137139
});
138140
}
@@ -174,7 +176,7 @@ pub fn block_on<F: Future<Output = T>, T>(future: F) -> T {
174176
use async_io::block_on;
175177
#[cfg(not(feature = "async-io"))]
176178
use future::block_on;
177-
LOCAL_EXECUTOR.with(|executor| block_on(executor.run(future)))
179+
enter02(|| LOCAL_EXECUTOR.with(|executor| block_on(executor.run(future))))
178180
}
179181

180182
/// Spawns a task onto the multi-threaded global executor.
@@ -226,3 +228,36 @@ pub fn spawn<F: Future<Output = T> + Send + 'static, T: Send + 'static>(future:
226228
pub fn spawn_local<F: Future<Output = T> + 'static, T: 'static>(future: F) -> Task<T> {
227229
LOCAL_EXECUTOR.with(|executor| executor.spawn(future))
228230
}
231+
232+
/// Enters the tokio context if the `tokio02` feature is enabled.
233+
fn enter02<T>(f: impl FnOnce() -> T) -> T {
234+
#[cfg(not(feature = "tokio02"))]
235+
return f();
236+
237+
#[cfg(feature = "tokio02")]
238+
{
239+
use std::cell::Cell;
240+
use tokio::runtime::Runtime;
241+
242+
thread_local! {
243+
/// The level of nested `enter` calls we are in, to ensure that the outermost always
244+
/// has a runtime spawned.
245+
static NESTING: Cell<usize> = Cell::new(0);
246+
}
247+
248+
/// The global tokio runtime.
249+
static RT: Lazy<Runtime> = new(|| Runtime::new().expect("cannot initialize tokio"));
250+
251+
NESTING.with(|nesting| {
252+
let res = if nesting.get() == 0 {
253+
nesting.replace(1);
254+
RT.enter(f)
255+
} else {
256+
nesting.replace(nesting.get() + 1);
257+
f()
258+
};
259+
nesting.replace(nesting.get() - 1);
260+
res
261+
})
262+
}
263+
}

0 commit comments

Comments
 (0)