#![deny(rust_2018_idioms, clippy::pedantic, warnings, missing_docs)]
pub mod executor;
pub mod join_handle;
#[cfg(feature = "attributes")]
pub use agnostik_attributes::{bench, main, test};
use join_handle::JoinHandle;
#[allow(unused)]
use once_cell::sync::Lazy;
use std::future::Future;
#[cfg(bastion)]
static EXECUTOR: Lazy<executor::BastionExecutor> = Lazy::new(|| executor::BastionExecutor);
#[cfg(async_std)]
static EXECUTOR: Lazy<executor::AsyncStdExecutor> = Lazy::new(|| executor::AsyncStdExecutor);
#[cfg(tokio)]
static EXECUTOR: Lazy<executor::TokioExecutor> = Lazy::new(|| executor::TokioExecutor::new());
#[cfg(smol)]
static EXECUTOR: Lazy<executor::SmolExecutor> = Lazy::new(|| executor::SmolExecutor);
pub trait AgnostikExecutor {
fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
where
F: Future + Send + 'static,
F::Output: Send + 'static;
fn spawn_blocking<F, T>(&self, task: F) -> JoinHandle<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static;
fn block_on<F>(&self, future: F) -> F::Output
where
F: Future + Send + 'static,
F::Output: Send + 'static;
}
pub trait LocalAgnostikExecutor: AgnostikExecutor {
fn spawn_local<F>(&self, future: F) -> JoinHandle<F::Output>
where
F: Future + 'static,
F::Output: 'static;
}
pub struct Agnostik;
impl Agnostik {
#[cfg(bastion)]
pub fn bastion() -> impl AgnostikExecutor {
executor::BastionExecutor::new()
}
#[cfg(async_std)]
pub fn async_std() -> impl LocalAgnostikExecutor {
executor::AsyncStdExecutor::new()
}
#[cfg(tokio)]
pub fn tokio() -> impl LocalAgnostikExecutor {
executor::TokioExecutor::new()
}
#[cfg(tokio)]
pub fn tokio_with_runtime(
runtime: tokio_crate::runtime::Runtime,
) -> impl LocalAgnostikExecutor {
executor::TokioExecutor::with_runtime(runtime)
}
#[cfg(smol)]
pub fn smol() -> impl AgnostikExecutor {
executor::SmolExecutor
}
}
pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
executor().spawn(future)
}
pub fn spawn_blocking<F, T>(task: F) -> JoinHandle<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
executor().spawn_blocking(task)
}
pub fn block_on<F>(future: F) -> F::Output
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
executor().block_on(future)
}
#[cfg(spawn_local)]
pub fn spawn_local<F>(future: F) -> JoinHandle<F::Output>
where
F: Future + 'static,
F::Output: 'static,
{
executor().spawn_local(future)
}
#[cfg(tokio)]
pub fn set_runtime(runtime: tokio_crate::runtime::Runtime) {
use std::any::Any;
let executor = executor() as &dyn Any;
match executor.downcast_ref::<executor::TokioExecutor>() {
Some(executor) => executor.set_runtime(runtime),
None => unreachable!(),
}
}
#[cfg(not(local_spawn))]
pub fn executor() -> &'static impl AgnostikExecutor {
#[cfg(enable)]
return &*EXECUTOR;
#[cfg(not(enable))]
{
struct PanicExecutor;
impl AgnostikExecutor for PanicExecutor {
fn spawn<F>(&self, _: F) -> JoinHandle<F::Output>
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
panic!("no runtime feature enabled.")
}
fn spawn_blocking<F, T>(&self, _: F) -> JoinHandle<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
panic!("no runtime feature enabled.")
}
fn block_on<F>(&self, _: F) -> F::Output
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
panic!("no runtime feature enabled.")
}
}
&PanicExecutor
}
}
#[cfg(local_spawn)]
pub fn executor() -> &'static impl LocalAgnostikExecutor {
&*EXECUTOR
}
#[allow(unused)]
pub mod prelude {
pub use crate::{block_on, spawn, spawn_blocking};
pub use crate::{Agnostik, AgnostikExecutor, LocalAgnostikExecutor};
}