#![doc = include_str!("../README.md")]
#![cfg_attr(not(any(feature = "std", test)), no_std)]
#![forbid(unsafe_code)]
#![deny(warnings, missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, allow(unused_attributes))]
#[cfg(any(feature = "std", test))]
extern crate std;
use core::future::Future;
#[cfg(feature = "time")]
use std::time::{Duration, Instant};
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
pub mod time;
#[cfg(feature = "tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
pub mod tokio;
#[cfg(feature = "async-std")]
#[cfg_attr(docsrs, doc(cfg(feature = "async-std")))]
pub mod async_std;
#[cfg(feature = "smol")]
#[cfg_attr(docsrs, doc(cfg(feature = "smol")))]
pub mod smol;
#[cfg(feature = "wasm")]
#[cfg_attr(docsrs, doc(cfg(feature = "wasm")))]
pub mod wasm;
#[cfg(feature = "async-io")]
#[cfg_attr(docsrs, doc(cfg(feature = "async-io")))]
pub mod async_io;
mod spawner;
pub use spawner::*;
pub trait RuntimeLite: Sized + Unpin + Copy + Send + Sync + 'static {
type Spawner: AsyncSpawner;
type LocalSpawner: AsyncLocalSpawner;
type BlockingSpawner: AsyncBlockingSpawner;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type AfterSpawner: AsyncAfterSpawner;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type LocalAfterSpawner: AsyncLocalAfterSpawner;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type Interval: time::AsyncInterval;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type LocalInterval: time::AsyncLocalInterval;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type Sleep: time::AsyncSleep;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type LocalSleep: time::AsyncLocalSleep;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type Delay<F>: time::AsyncDelay<F>
where
F: Future + Send;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type LocalDelay<F>: time::AsyncLocalDelay<F>
where
F: Future;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type Timeout<F>: time::AsyncTimeout<F>
where
F: Future + Send;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
type LocalTimeout<F>: time::AsyncLocalTimeout<F>
where
F: Future;
fn new() -> Self;
fn spawn<F>(future: F) -> <Self::Spawner as AsyncSpawner>::JoinHandle<F::Output>
where
F::Output: Send + 'static,
F: Future + Send + 'static,
{
<Self::Spawner as AsyncSpawner>::spawn(future)
}
fn spawn_detach<F>(future: F)
where
F::Output: Send + 'static,
F: Future + Send + 'static,
{
<Self::Spawner as AsyncSpawner>::spawn_detach(future);
}
fn spawn_local<F>(future: F) -> <Self::LocalSpawner as AsyncLocalSpawner>::JoinHandle<F::Output>
where
F: Future + 'static,
F::Output: 'static,
{
<Self::LocalSpawner as AsyncLocalSpawner>::spawn_local(future)
}
fn spawn_local_detach<F>(future: F)
where
F: Future + 'static,
F::Output: 'static,
{
<Self::LocalSpawner as AsyncLocalSpawner>::spawn_local_detach(future)
}
fn spawn_blocking<F, R>(f: F) -> <Self::BlockingSpawner as AsyncBlockingSpawner>::JoinHandle<R>
where
F: FnOnce() -> R + Send + 'static,
R: Send + 'static,
{
<Self::BlockingSpawner as AsyncBlockingSpawner>::spawn_blocking(f)
}
fn spawn_blocking_detach<F, R>(f: F)
where
F: FnOnce() -> R + Send + 'static,
R: Send + 'static,
{
<Self::BlockingSpawner as AsyncBlockingSpawner>::spawn_blocking_detach(f);
}
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn spawn_after<F>(
duration: core::time::Duration,
future: F,
) -> <Self::AfterSpawner as AsyncAfterSpawner>::JoinHandle<F::Output>
where
F::Output: Send + 'static,
F: Future + Send + 'static,
{
<Self::AfterSpawner as AsyncAfterSpawner>::spawn_after(duration, future)
}
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn spawn_after_at<F>(
at: std::time::Instant,
future: F,
) -> <Self::AfterSpawner as AsyncAfterSpawner>::JoinHandle<F::Output>
where
F::Output: Send + 'static,
F: Future + Send + 'static,
{
<Self::AfterSpawner as AsyncAfterSpawner>::spawn_after_at(at, future)
}
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn spawn_local_after<F>(
duration: core::time::Duration,
future: F,
) -> <Self::LocalAfterSpawner as AsyncLocalAfterSpawner>::JoinHandle<F::Output>
where
F::Output: Send + 'static,
F: Future + Send + 'static,
{
<Self::LocalAfterSpawner as AsyncLocalAfterSpawner>::spawn_local_after(duration, future)
}
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn spawn_local_after_at<F>(
at: std::time::Instant,
future: F,
) -> <Self::LocalAfterSpawner as AsyncLocalAfterSpawner>::JoinHandle<F::Output>
where
F::Output: Send + 'static,
F: Future + Send + 'static,
{
<Self::LocalAfterSpawner as AsyncLocalAfterSpawner>::spawn_local_after_at(at, future)
}
fn block_on<F: Future>(f: F) -> F::Output;
fn yield_now() -> impl Future<Output = ()> + Send;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn interval(interval: Duration) -> Self::Interval;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn interval_at(start: Instant, period: Duration) -> Self::Interval;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn interval_local(interval: Duration) -> Self::LocalInterval;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn interval_local_at(start: Instant, period: Duration) -> Self::LocalInterval;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn sleep(duration: Duration) -> Self::Sleep;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn sleep_until(instant: Instant) -> Self::Sleep;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn sleep_local(duration: Duration) -> Self::LocalSleep;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn sleep_local_until(instant: Instant) -> Self::LocalSleep;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn delay<F>(duration: Duration, fut: F) -> Self::Delay<F>
where
F: Future + Send;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn delay_local<F>(duration: Duration, fut: F) -> Self::LocalDelay<F>
where
F: Future;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn delay_at<F>(deadline: Instant, fut: F) -> Self::Delay<F>
where
F: Future + Send;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn delay_local_at<F>(deadline: Instant, fut: F) -> Self::LocalDelay<F>
where
F: Future;
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn timeout<F>(duration: Duration, future: F) -> Self::Timeout<F>
where
F: Future + Send,
{
<Self::Timeout<F> as time::AsyncTimeout<F>>::timeout(duration, future)
}
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn timeout_at<F>(deadline: Instant, future: F) -> Self::Timeout<F>
where
F: Future + Send,
{
<Self::Timeout<F> as time::AsyncTimeout<F>>::timeout_at(deadline, future)
}
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn timeout_local<F>(duration: Duration, future: F) -> Self::LocalTimeout<F>
where
F: Future,
{
<Self::LocalTimeout<F> as time::AsyncLocalTimeout<F>>::timeout_local(duration, future)
}
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
fn timeout_local_at<F>(deadline: Instant, future: F) -> Self::LocalTimeout<F>
where
F: Future,
{
<Self::LocalTimeout<F> as time::AsyncLocalTimeout<F>>::timeout_local_at(deadline, future)
}
}
#[cfg(any(test, feature = "test"))]
#[cfg_attr(docsrs, doc(cfg(any(test, feature = "test"))))]
pub mod tests {
use core::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use super::*;
pub async fn spawn_after_unittest<R: RuntimeLite>() {
let ctr = Arc::new(AtomicUsize::new(1));
let ctr1 = ctr.clone();
let handle = R::spawn_after(Duration::from_secs(1), async move {
ctr1.fetch_add(1, Ordering::SeqCst);
});
R::sleep(Duration::from_millis(500)).await;
assert_eq!(ctr.load(Ordering::SeqCst), 1);
handle.await.unwrap();
assert_eq!(ctr.load(Ordering::SeqCst), 2);
}
pub async fn spawn_after_cancel_unittest<R: RuntimeLite>() {
let ctr = Arc::new(AtomicUsize::new(1));
let ctr1 = ctr.clone();
let handle = R::spawn_after(Duration::from_secs(1), async move {
ctr1.fetch_add(1, Ordering::SeqCst);
});
R::sleep(Duration::from_millis(500)).await;
assert_eq!(ctr.load(Ordering::SeqCst), 1);
let o = handle.cancel().await;
assert!(o.is_none());
assert_eq!(ctr.load(Ordering::SeqCst), 1);
}
pub async fn spawn_after_drop_unittest<R: RuntimeLite>() {
let ctr = Arc::new(AtomicUsize::new(1));
let ctr1 = ctr.clone();
drop(R::spawn_after(Duration::from_secs(1), async move {
ctr1.fetch_add(1, Ordering::SeqCst);
}));
R::sleep(Duration::from_millis(500)).await;
assert_eq!(ctr.load(Ordering::SeqCst), 1);
R::sleep(Duration::from_millis(600)).await;
assert_eq!(ctr.load(Ordering::SeqCst), 2);
}
}