Skip to content

Commit fb845a6

Browse files
committed
Introduce WithExecutor adaptor
1 parent 112672c commit fb845a6

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

futures-core/src/task/context.rs

+13
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,19 @@ if_std! {
110110
.expect("No default executor found")
111111
.spawn(Box::new(f)).unwrap()
112112
}
113+
114+
/// Produce a context like the current one, but using the given executor
115+
/// instead.
116+
///
117+
/// This advanced method is primarily used when building "internal
118+
/// schedulers" within a task.
119+
pub fn with_executor<'b>(&'b mut self, executor: &'b mut Executor)
120+
-> Context<'b>
121+
{
122+
self.with_parts(move |waker, map, _| {
123+
Context { map, executor: Some(executor), waker }
124+
})
125+
}
113126
}
114127
}
115128

futures-util/src/future/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,13 @@ if_std! {
6161
mod select_all;
6262
mod select_ok;
6363
mod shared;
64+
mod with_executor;
6465
pub use self::catch_unwind::CatchUnwind;
6566
pub use self::join_all::{join_all, JoinAll};
6667
pub use self::select_all::{SelectAll, SelectAllNext, select_all};
6768
pub use self::select_ok::{SelectOk, select_ok};
6869
pub use self::shared::{Shared, SharedItem, SharedError};
70+
pub use self::with_executor::WithExecutor;
6971
}
7072

7173
impl<T: ?Sized> FutureExt for T where T: Future {}
@@ -875,6 +877,33 @@ pub trait FutureExt: Future {
875877
{
876878
recover::new(self, f)
877879
}
880+
881+
/// Assigns the provided `Executor` to be used when spawning tasks
882+
/// from within the future.
883+
///
884+
/// # Examples
885+
///
886+
/// ```
887+
/// # extern crate futures;
888+
/// # extern crate futures_executor;
889+
/// use futures::prelude::*;
890+
/// use futures::future;
891+
/// use futures_executor::{block_on, spawn, ThreadPool};
892+
///
893+
/// # fn main() {
894+
/// let pool = ThreadPool::new();
895+
/// let future = future::ok::<(), _>(());
896+
/// let spawn_future = spawn(future).with_executor(pool);
897+
/// assert_eq!(block_on(spawn_future), Ok(()));
898+
/// # }
899+
/// ```
900+
#[cfg(feature = "std")]
901+
fn with_executor<E>(self, executor: E) -> WithExecutor<Self, E>
902+
where Self: Sized,
903+
E: ::futures_core::executor::Executor
904+
{
905+
with_executor::new(self, executor)
906+
}
878907
}
879908

880909
// Just a helper function to ensure the futures we're returning all have the
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use futures_core::{Future, Poll};
2+
use futures_core::task;
3+
use futures_core::executor::Executor;
4+
5+
/// Future for the `with_executor` combinator, assigning an executor
6+
/// to be used when spawning other futures.
7+
///
8+
/// This is created by the `Future::with_executor` method.
9+
#[derive(Debug)]
10+
#[must_use = "futures do nothing unless polled"]
11+
pub struct WithExecutor<F, E> where F: Future, E: Executor {
12+
executor: E,
13+
future: F
14+
}
15+
16+
pub fn new<F, E>(future: F, executor: E) -> WithExecutor<F, E>
17+
where F: Future,
18+
E: Executor,
19+
{
20+
WithExecutor { executor, future }
21+
}
22+
23+
impl<F, E> Future for WithExecutor<F, E>
24+
where F: Future,
25+
E: Executor,
26+
{
27+
type Item = F::Item;
28+
type Error = F::Error;
29+
30+
fn poll(&mut self, cx: &mut task::Context) -> Poll<F::Item, F::Error> {
31+
self.future.poll(&mut cx.with_executor(&mut self.executor))
32+
}
33+
}

0 commit comments

Comments
 (0)