use std::future::Future;
use anyhow::Result;
fn run_future<F, T>(future: F) -> Result<T>
where
F: Future<Output = T>,
{
if let Ok(handle) = tokio::runtime::Handle::try_current() {
return Ok(tokio::task::block_in_place(|| handle.block_on(future)));
}
Ok(tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?
.block_on(future))
}
pub fn block_on<F, T>(future: F) -> T
where
F: Future<Output = T>,
{
run_future(future).expect("failed to run async task")
}
pub fn try_block_on<F, T>(future: F) -> Result<T>
where
F: Future<Output = T>,
{
run_future(future)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn try_block_on_works_outside_runtime() {
let value = try_block_on(async { 42 }).expect("outside runtime");
assert_eq!(value, 42);
}
#[tokio::test(flavor = "multi_thread")]
async fn try_block_on_works_inside_runtime() {
let value = try_block_on(async { 42 }).expect("inside runtime");
assert_eq!(value, 42);
}
}