chore: make TaskSpawner dyncloneable (#1354)

This commit is contained in:
Matthias Seitz
2023-02-14 20:46:37 +01:00
committed by GitHub
parent d5d685b5b2
commit 87ba4840e9
3 changed files with 65 additions and 7 deletions

7
Cargo.lock generated
View File

@ -1378,6 +1378,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "dyn-clone"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9b0705efd4599c15a38151f4721f7bc388306f61084d3bfd50bd07fbca5cb60"
[[package]]
name = "ecdsa"
version = "0.14.8"
@ -4774,6 +4780,7 @@ dependencies = [
name = "reth-tasks"
version = "0.1.0"
dependencies = [
"dyn-clone",
"futures-util",
"thiserror",
"tokio",

View File

@ -8,11 +8,16 @@ readme = "README.md"
description = "Task management"
[dependencies]
## async
tokio = { version = "1", features = ["sync", "rt"] }
tracing-futures = "0.2"
tracing = { version = "0.1", default-features = false }
futures-util = "0.3"
## misc
tracing = { version = "0.1", default-features = false }
thiserror = "1.0"
dyn-clone = "1.0"
[dev-dependencies]
tokio = { version = "1", features = ["sync", "rt", "rt-multi-thread", "time", "macros"] }

View File

@ -8,6 +8,7 @@
//! reth task management
use crate::shutdown::{signal, Shutdown, Signal};
use dyn_clone::DynClone;
use futures_util::{
future::{select, BoxFuture},
pin_mut, Future, FutureExt,
@ -30,17 +31,48 @@ pub mod shutdown;
///
/// The main purpose of this type is to abstract over [TaskExecutor] so it's more convenient to
/// provide default impls for testing.
pub trait TaskSpawner: Send + Sync {
///
///
/// # Examples
///
/// Use the [TokioTaskExecutor] that spawns with [tokio::task::spawn]
///
/// ```
/// # async fn t() {
/// use reth_tasks::{TaskSpawner, TokioTaskExecutor};
/// let executor = TokioTaskExecutor::default();
///
/// let task = executor.spawn(Box::pin(async {
/// // -- snip --
/// }));
/// task.await.unwrap();
/// # }
/// ```
///
/// Use the [TaskExecutor] that spawns task directly onto the tokio runtime via the [Handle].
///
/// ```
/// # use reth_tasks::TaskManager;
/// fn t() {
/// use reth_tasks::TaskSpawner;
/// let rt = tokio::runtime::Runtime::new().unwrap();
/// let manager = TaskManager::new(rt.handle().clone());
/// let executor = manager.executor();
/// let task = TaskSpawner::spawn(&executor, Box::pin(async {
/// // -- snip --
/// }));
/// rt.block_on(task).unwrap();
/// # }
/// ```
///
/// The [TaskSpawner] trait is [DynClone] so `Box<dyn TaskSpawner>` are also `Clone`.
pub trait TaskSpawner: Send + Sync + DynClone {
/// Spawns the task onto the runtime.
/// See also [`Handle::spawn`].
fn spawn(&self, fut: BoxFuture<'static, ()>) -> JoinHandle<()>;
}
impl TaskSpawner for Box<dyn TaskSpawner> {
fn spawn(&self, fut: BoxFuture<'static, ()>) -> JoinHandle<()> {
(**self).spawn(fut)
}
}
dyn_clone::clone_trait_object!(TaskSpawner);
/// An [TaskSpawner] that uses [tokio::task::spawn] to execute tasks
#[derive(Debug, Clone, Default)]
@ -313,6 +345,20 @@ mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_cloneable() {
#[derive(Clone)]
struct ExecutorWrapper {
_e: Box<dyn TaskSpawner>,
}
let executor: Box<dyn TaskSpawner> = Box::<TokioTaskExecutor>::default();
let _e = dyn_clone::clone_box(&*executor);
let e = ExecutorWrapper { _e };
let _e2 = e;
}
#[test]
fn test_critical() {
let runtime = tokio::runtime::Runtime::new().unwrap();