use futures::FutureExt;
pub use futures::future::BoxFuture; use near_time::Duration;
use std::sync::Arc;
pub trait FutureSpawner: Send + Sync {
fn spawn_boxed(&self, description: &'static str, f: BoxFuture<'static, ()>);
}
pub trait FutureSpawnerExt {
fn spawn<F>(&self, description: &'static str, f: F)
where
F: futures::Future<Output = ()> + Send + 'static;
}
impl<T: FutureSpawner> FutureSpawnerExt for T {
fn spawn<F>(&self, description: &'static str, f: F)
where
F: futures::Future<Output = ()> + Send + 'static,
{
self.spawn_boxed(description, f.boxed());
}
}
impl FutureSpawnerExt for dyn FutureSpawner + '_ {
fn spawn<F>(&self, description: &'static str, f: F)
where
F: futures::Future<Output = ()> + Send + 'static,
{
self.spawn_boxed(description, f.boxed());
}
}
pub fn respawn_for_parallelism<T: Send + 'static>(
future_spawner: &dyn FutureSpawner,
name: &'static str,
f: impl std::future::Future<Output = T> + Send + 'static,
) -> impl std::future::Future<Output = T> + Send + 'static {
let (sender, receiver) = tokio::sync::oneshot::channel();
future_spawner.spawn(name, async move {
sender.send(f.await).ok();
});
async move { receiver.await.unwrap() }
}
pub struct TokioRuntimeFutureSpawner(pub Arc<tokio::runtime::Runtime>);
impl FutureSpawner for TokioRuntimeFutureSpawner {
fn spawn_boxed(&self, _description: &'static str, f: BoxFuture<'static, ()>) {
self.0.spawn(f);
}
}
pub struct DirectTokioFutureSpawnerForTest;
impl FutureSpawner for DirectTokioFutureSpawnerForTest {
fn spawn_boxed(&self, _description: &'static str, f: BoxFuture<'static, ()>) {
tokio::spawn(f);
}
}
pub trait DelayedActionRunner<T> {
fn run_later_boxed(
&mut self,
name: &'static str,
dur: Duration,
f: Box<dyn FnOnce(&mut T, &mut dyn DelayedActionRunner<T>) + Send + 'static>,
);
}
pub trait DelayedActionRunnerExt<T> {
fn run_later(
&mut self,
name: &'static str,
dur: Duration,
f: impl FnOnce(&mut T, &mut dyn DelayedActionRunner<T>) + Send + 'static,
);
}
impl<T, Runner> DelayedActionRunnerExt<T> for Runner
where
Runner: DelayedActionRunner<T>,
{
fn run_later(
&mut self,
name: &'static str,
dur: Duration,
f: impl FnOnce(&mut T, &mut dyn DelayedActionRunner<T>) + Send + 'static,
) {
self.run_later_boxed(name, dur, Box::new(f));
}
}
impl<T> DelayedActionRunnerExt<T> for dyn DelayedActionRunner<T> + '_ {
fn run_later(
&mut self,
name: &'static str,
dur: Duration,
f: impl FnOnce(&mut T, &mut dyn DelayedActionRunner<T>) + Send + 'static,
) {
self.run_later_boxed(name, dur, Box::new(f));
}
}
pub trait AsyncComputationSpawner: Send + Sync {
fn spawn_boxed(&self, name: &str, f: Box<dyn FnOnce() + Send>);
}
pub trait AsyncComputationSpawnerExt {
fn spawn(&self, name: &str, f: impl FnOnce() + Send + 'static);
}
impl<T: AsyncComputationSpawner> AsyncComputationSpawnerExt for T {
fn spawn(&self, name: &str, f: impl FnOnce() + Send + 'static) {
self.spawn_boxed(name, Box::new(f));
}
}
impl AsyncComputationSpawnerExt for dyn AsyncComputationSpawner + '_ {
fn spawn(&self, name: &str, f: impl FnOnce() + Send + 'static) {
self.spawn_boxed(name, Box::new(f));
}
}
pub struct StdThreadAsyncComputationSpawnerForTest;
impl AsyncComputationSpawner for StdThreadAsyncComputationSpawnerForTest {
fn spawn_boxed(&self, _name: &str, f: Box<dyn FnOnce() + Send>) {
std::thread::spawn(f);
}
}