Allow any closure to be passed as an executor (#1686)

Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
This commit is contained in:
Thomas Eizinger 2020-09-03 19:28:15 +10:00 committed by GitHub
parent 6a1279407e
commit 3100444085
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 36 deletions

View File

@ -78,20 +78,8 @@ pub trait Executor {
fn exec(&self, future: Pin<Box<dyn Future<Output = ()> + Send>>);
}
impl<'a, T: ?Sized + Executor> Executor for &'a T {
impl<F: Fn(Pin<Box<dyn Future<Output = ()> + Send>>)> Executor for F {
fn exec(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) {
T::exec(&**self, f)
}
}
impl<'a, T: ?Sized + Executor> Executor for &'a mut T {
fn exec(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) {
T::exec(&**self, f)
}
}
impl<T: ?Sized + Executor> Executor for Box<T> {
fn exec(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) {
T::exec(&**self, f)
self(f)
}
}

View File

@ -633,18 +633,6 @@ impl NetworkConfig {
self
}
/// Shortcut for calling `executor` with an object that calls the given closure.
pub fn set_executor_fn(mut self, f: impl Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + 'static) -> Self {
struct SpawnImpl<F>(F);
impl<F: Fn(Pin<Box<dyn Future<Output = ()> + Send>>)> Executor for SpawnImpl<F> {
fn exec(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) {
(self.0)(f)
}
}
self.set_executor(Box::new(SpawnImpl(f)));
self
}
pub fn executor(&self) -> Option<&Box<dyn Executor + Send>> {
self.manager_config.executor.as_ref()
}
@ -692,3 +680,24 @@ impl NetworkConfig {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
struct Dummy;
impl Executor for Dummy {
fn exec(&self, _: Pin<Box<dyn Future<Output=()> + Send>>) { }
}
#[test]
fn set_executor() {
NetworkConfig::default()
.set_executor(Box::new(Dummy))
.set_executor(Box::new(|f| {
async_std::task::spawn(f);
}));
}
}

View File

@ -89,7 +89,7 @@ use protocols_handler::{
};
use futures::{
prelude::*,
executor::{ThreadPool, ThreadPoolBuilder},
executor::ThreadPoolBuilder,
stream::FusedStream,
};
use libp2p_core::{
@ -1095,19 +1095,13 @@ where TBehaviour: NetworkBehaviour,
// If no executor has been explicitly configured, try to set up a thread pool.
if network_cfg.executor().is_none() {
struct PoolWrapper(ThreadPool);
impl Executor for PoolWrapper {
fn exec(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) {
self.0.spawn_ok(f)
}
}
match ThreadPoolBuilder::new()
.name_prefix("libp2p-swarm-task-")
.create()
.map(|tp| Box::new(PoolWrapper(tp)) as Box<_>)
{
Ok(executor) => { network_cfg.set_executor(Box::new(executor)); },
Ok(tp) => {
network_cfg.set_executor(Box::new(move |f| tp.spawn_ok(f)));
},
Err(err) => log::warn!("Failed to create executor thread pool: {:?}", err)
}
}