use std::future::Future;
use std::sync::Arc;
use tokio::task::{JoinError, JoinHandle};
use crate::prelude::*;
impl<T: Send> TaskHandle for JoinHandle<Result<T, JoinError>> {
type Output = T;
type JoinError = JoinError;
async fn join(self) -> Result<Self::Output, Self::JoinError> {
self.await?
}
fn abort(self) {
JoinHandle::abort(&self);
}
async fn cancel(self) {
JoinHandle::abort(&self);
let _ = self.await;
}
fn detach(self) {}
}
#[derive(Clone)]
pub struct Runtime {
#[allow(dead_code)]
runtime: Option<Arc<tokio::runtime::Runtime>>,
handle: tokio::runtime::Handle,
}
impl Runtime {
pub fn current() -> Runtime {
Self {
runtime: None,
handle: tokio::runtime::Handle::current(),
}
}
}
impl From<tokio::runtime::Handle> for Runtime {
fn from(handle: tokio::runtime::Handle) -> Self {
Self {
runtime: None,
handle,
}
}
}
impl From<&tokio::runtime::Handle> for Runtime {
fn from(handle: &tokio::runtime::Handle) -> Self {
Self {
runtime: None,
handle: handle.to_owned(),
}
}
}
impl crate::TaskInterface for Runtime {
type TaskHandle<T: 'static + Send> = JoinHandle<Result<T, Self::JoinError>>;
type SpawnError = Infallible;
type JoinError = JoinError;
fn spawn_task<F, T>(
&self,
future: F,
) -> Result<crate::utils::TaskHandle<Self::TaskHandle<F::Output>>, Self::SpawnError>
where
F: Future<Output = T> + Send + 'static,
T: Send + 'static,
{
Ok(self.handle.spawn(async move { Ok(future.await) }).into())
}
fn block_on<F: Future>(&self, future: F) -> F::Output {
self.handle.block_on(future)
}
}
impl CreationInterface for Runtime {
type NewError = std::io::Error;
fn new(config: Config) -> Result<Self, Self::NewError> {
let mut builder = tokio::runtime::Builder::new_multi_thread();
builder.enable_all();
if let Some(prefix) = config.prefix {
builder.thread_name(prefix);
}
if let Some(thread_count) = config.thread_count {
builder.worker_threads(thread_count);
}
let runtime = builder.build()?;
let handle = runtime.handle().clone();
Ok(Self {
runtime: Some(Arc::new(runtime)),
handle,
})
}
}