Skip to content

Commit 3ff5730

Browse files
committed
executor: add spawner
This allows spawning a task on an executor from outside of it Fixes #1 Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
1 parent c7bfd46 commit 3ff5730

File tree

1 file changed

+77
-4
lines changed

1 file changed

+77
-4
lines changed

src/lib.rs

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
use std::future::Future;
3232
use std::pin::Pin;
33+
use std::sync::Arc;
3334
use std::task::{Context, Poll};
3435
use std::time::Duration;
3536

@@ -72,7 +73,7 @@ scoped_thread_local!(static LOCAL_EX: LocalExecutor);
7273
/// ```
7374
#[derive(Debug)]
7475
pub struct Executor {
75-
ex: multitask::Executor,
76+
ex: Arc<multitask::Executor>,
7677
}
7778

7879
impl Executor {
@@ -81,13 +82,29 @@ impl Executor {
8182
/// # Examples
8283
///
8384
/// ```
84-
/// use async_executor::LocalExecutor;
85+
/// use async_executor::Executor;
8586
///
86-
/// let local_ex = LocalExecutor::new();
87+
/// let ex = Executor::new();
8788
/// ```
8889
pub fn new() -> Executor {
8990
Executor {
90-
ex: multitask::Executor::new(),
91+
ex: Arc::new(multitask::Executor::new()),
92+
}
93+
}
94+
95+
/// Creates a spawner for this executor.
96+
///
97+
/// # Examples
98+
///
99+
/// ```
100+
/// use async_executor::Executor;
101+
///
102+
/// let ex = Executor::new();
103+
/// let spawner = ex.spawner();
104+
/// ```
105+
pub fn spawner(&self) -> Spawner {
106+
Spawner {
107+
ex: self.ex.clone(),
91108
}
92109
}
93110

@@ -184,6 +201,62 @@ impl Default for Executor {
184201
}
185202
}
186203

204+
/// A spawner for a multi-threaded executor.
205+
#[derive(Debug)]
206+
pub struct Spawner {
207+
ex: Arc<multitask::Executor>,
208+
}
209+
210+
impl Spawner {
211+
/// Get a Spawner for the current multi-threaded executor.
212+
///
213+
/// If called from an [`Executor`], get its Spawner.
214+
///
215+
/// Otherwise, this method panics.
216+
///
217+
/// # Examples
218+
///
219+
/// ```
220+
/// use async_executor::{Executor, Spawner};
221+
///
222+
/// let ex = Executor::new();
223+
///
224+
/// ex.run(async {
225+
/// let spawner = Spawner::current();
226+
/// let task = spawner.spawn(async { 1 + 2 });
227+
/// assert_eq!(task.await, 3);
228+
/// });
229+
/// ```
230+
pub fn current() -> Spawner {
231+
if EX.is_set() {
232+
EX.with(|ex| ex.spawner())
233+
} else {
234+
panic!("`Spawner::current()` must be called from an `Executor`")
235+
}
236+
}
237+
238+
/// Spawns a task onto the executor.
239+
///
240+
/// # Examples
241+
///
242+
/// ```
243+
/// use async_executor::Executor;
244+
///
245+
/// let ex = Executor::new();
246+
/// let spawner = ex.spawner();
247+
///
248+
/// let task = spawner.spawn(async {
249+
/// println!("Hello world");
250+
/// });
251+
/// ```
252+
pub fn spawn<T: Send + 'static>(
253+
&self,
254+
future: impl Future<Output = T> + Send + 'static,
255+
) -> Task<T> {
256+
Task(self.ex.spawn(future))
257+
}
258+
}
259+
187260
/// Single-threaded executor.
188261
///
189262
/// The executor can only be run on the thread that created it.

0 commit comments

Comments
 (0)