use std::future::Future;
use crate::Error;
#[derive(Debug)]
pub struct Runtime {
inner: Option<tokio::runtime::Runtime>,
}
impl Runtime {
pub fn new() -> Result<Self, Error> {
let inner = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(Error::runtime_unavailable)?;
Ok(Self { inner: Some(inner) })
}
pub fn run<F: Future>(&self, future: F) -> F::Output {
self.runtime().block_on(future)
}
pub fn try_run<F: Future>(&self, future: F) -> Result<F::Output, Error> {
if tokio::runtime::Handle::try_current().is_ok() {
return Err(Error::RuntimeNested);
}
Ok(self.runtime().block_on(future))
}
fn runtime(&self) -> &tokio::runtime::Runtime {
let Some(runtime) = self.inner.as_ref() else {
unreachable!("only Drop takes the runtime, and it holds &mut self")
};
runtime
}
}
impl Drop for Runtime {
fn drop(&mut self) {
let Some(runtime) = self.inner.take() else {
return;
};
if tokio::runtime::Handle::try_current().is_ok() {
runtime.shutdown_background();
}
}
}