use once_cell::sync::Lazy;
use tokio::runtime::Runtime;
pub static TOKIO: Lazy<Runtime> = Lazy::new(new_runtime);
fn new_runtime() -> Runtime {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.thread_name("holochain-tokio-thread")
.build()
.expect("can build tokio runtime")
}
fn block_on_given<F>(f: F, runtime: &Runtime) -> F::Output
where
F: futures::future::Future,
{
let _g = runtime.enter();
tokio::task::block_in_place(|| runtime.block_on(async { f.await }))
}
pub fn block_on<F>(
f: F,
timeout: std::time::Duration,
) -> Result<F::Output, tokio::time::error::Elapsed>
where
F: futures::future::Future,
{
block_on_given(tokio::time::timeout(timeout, f), &TOKIO)
}
pub fn block_forever_on<F>(f: F) -> F::Output
where
F: futures::future::Future,
{
block_on_given(f, &TOKIO)
}
#[cfg(test)]
mod test {
use super::*;
#[tokio::test(flavor = "multi_thread")]
async fn block_on_works() {
block_forever_on(async { println!("stdio can block") });
assert_eq!(1, super::block_forever_on(async { 1 }));
let r = "1";
let test1 = super::block_forever_on(async { r.to_string() });
assert_eq!("1", &test1);
let test2 = std::thread::spawn(|| {
let r = "2";
super::block_forever_on(async { r.to_string() })
})
.join()
.unwrap();
assert_eq!("2", &test2);
}
#[tokio::test(flavor = "multi_thread")]
async fn block_on_allows_spawning() {
let r = "works";
let test = block_forever_on(tokio::task::spawn(async move { r.to_string() })).unwrap();
assert_eq!("works", &test);
}
}