Add spawn_local function
diff --git a/examples/panic-propagation.rs b/examples/panic-propagation.rs
index 8a5339f..05ec85a 100644
--- a/examples/panic-propagation.rs
+++ b/examples/panic-propagation.rs
@@ -11,6 +11,8 @@
use futures::future::FutureExt;
use lazy_static::lazy_static;
+type Task = async_task::Task<()>;
+
/// Spawns a future on the executor.
fn spawn<F, R>(future: F) -> JoinHandle<R>
where
@@ -19,8 +21,8 @@
{
lazy_static! {
// A channel that holds scheduled tasks.
- static ref QUEUE: Sender<async_task::Task<()>> = {
- let (sender, receiver) = unbounded::<async_task::Task<()>>();
+ static ref QUEUE: Sender<Task> = {
+ let (sender, receiver) = unbounded::<Task>();
// Start the executor thread.
thread::spawn(|| {
diff --git a/examples/panic-result.rs b/examples/panic-result.rs
index 7cf5a14..6308240 100644
--- a/examples/panic-result.rs
+++ b/examples/panic-result.rs
@@ -9,16 +9,19 @@
use futures::future::FutureExt;
use lazy_static::lazy_static;
+type Task = async_task::Task<()>;
+type JoinHandle<T> = async_task::JoinHandle<T, ()>;
+
/// Spawns a future on the executor.
-fn spawn<F, R>(future: F) -> async_task::JoinHandle<thread::Result<R>, ()>
+fn spawn<F, R>(future: F) -> JoinHandle<thread::Result<R>>
where
F: Future<Output = R> + Send + 'static,
R: Send + 'static,
{
lazy_static! {
// A channel that holds scheduled tasks.
- static ref QUEUE: Sender<async_task::Task<()>> = {
- let (sender, receiver) = unbounded::<async_task::Task<()>>();
+ static ref QUEUE: Sender<Task> = {
+ let (sender, receiver) = unbounded::<Task>();
// Start the executor thread.
thread::spawn(|| {
diff --git a/examples/spawn-local.rs b/examples/spawn-local.rs
new file mode 100644
index 0000000..4e66c32
--- /dev/null
+++ b/examples/spawn-local.rs
@@ -0,0 +1,76 @@
+//! A simple single-threaded executor that can spawn non-`Send` futures.
+
+use std::cell::Cell;
+use std::future::Future;
+use std::rc::Rc;
+
+use crossbeam::channel::{unbounded, Receiver, Sender};
+
+type Task = async_task::Task<()>;
+type JoinHandle<T> = async_task::JoinHandle<T, ()>;
+
+thread_local! {
+ // A channel that holds scheduled tasks.
+ static QUEUE: (Sender<Task>, Receiver<Task>) = unbounded();
+}
+
+/// Spawns a future on the executor.
+fn spawn<F, R>(future: F) -> JoinHandle<R>
+where
+ F: Future<Output = R> + 'static,
+ R: 'static,
+{
+ // Create a task that is scheduled by sending itself into the channel.
+ let schedule = |t| QUEUE.with(|(s, _)| s.send(t).unwrap());
+ let (task, handle) = async_task::spawn_local(future, schedule, ());
+
+ // Schedule the task by sending it into the queue.
+ task.schedule();
+
+ handle
+}
+
+/// Runs a future to completion.
+fn run<F, R>(future: F) -> R
+where
+ F: Future<Output = R> + 'static,
+ R: 'static,
+{
+ // Spawn a task that sends its result through a channel.
+ let (s, r) = unbounded();
+ spawn(async move { s.send(future.await).unwrap() });
+
+ loop {
+ // If the original task has completed, return its result.
+ if let Ok(val) = r.try_recv() {
+ return val;
+ }
+
+ // Otherwise, take a task from the queue and run it.
+ QUEUE.with(|(_, r)| r.recv().unwrap().run());
+ }
+}
+
+fn main() {
+ let val = Rc::new(Cell::new(0));
+
+ // Run a future that increments a non-`Send` value.
+ run({
+ let val = val.clone();
+ async move {
+ // Spawn a future that increments the value.
+ let handle = spawn({
+ let val = val.clone();
+ async move {
+ val.set(dbg!(val.get()) + 1);
+ }
+ });
+
+ val.set(dbg!(val.get()) + 1);
+ handle.await;
+ }
+ });
+
+ // The value should be 2 at the end of the program.
+ dbg!(val.get());
+}
diff --git a/examples/spawn-on-thread.rs b/examples/spawn-on-thread.rs
index 22da0c5..95214ed 100644
--- a/examples/spawn-on-thread.rs
+++ b/examples/spawn-on-thread.rs
@@ -7,10 +7,12 @@
use crossbeam::channel;
use futures::executor;
+type JoinHandle<T> = async_task::JoinHandle<T, ()>;
+
/// Spawns a future on a new dedicated thread.
///
/// The returned handle can be used to await the output of the future.
-fn spawn_on_thread<F, R>(future: F) -> async_task::JoinHandle<R, ()>
+fn spawn_on_thread<F, R>(future: F) -> JoinHandle<R>
where
F: Future<Output = R> + Send + 'static,
R: Send + 'static,
diff --git a/examples/spawn.rs b/examples/spawn.rs
index 4af5a02..9db7215 100644
--- a/examples/spawn.rs
+++ b/examples/spawn.rs
@@ -8,16 +8,19 @@
use futures::executor;
use lazy_static::lazy_static;
+type Task = async_task::Task<()>;
+type JoinHandle<T> = async_task::JoinHandle<T, ()>;
+
/// Spawns a future on the executor.
-fn spawn<F, R>(future: F) -> async_task::JoinHandle<R, ()>
+fn spawn<F, R>(future: F) -> JoinHandle<R>
where
F: Future<Output = R> + Send + 'static,
R: Send + 'static,
{
lazy_static! {
// A channel that holds scheduled tasks.
- static ref QUEUE: Sender<async_task::Task<()>> = {
- let (sender, receiver) = unbounded::<async_task::Task<()>>();
+ static ref QUEUE: Sender<Task> = {
+ let (sender, receiver) = unbounded::<Task>();
// Start the executor thread.
thread::spawn(|| {
diff --git a/examples/task-id.rs b/examples/task-id.rs
index 66b7aec..2a7bcf7 100644
--- a/examples/task-id.rs
+++ b/examples/task-id.rs
@@ -13,6 +13,9 @@
#[derive(Clone, Copy, Debug)]
struct TaskId(usize);
+type Task = async_task::Task<TaskId>;
+type JoinHandle<T> = async_task::JoinHandle<T, TaskId>;
+
thread_local! {
/// The ID of the current task.
static TASK_ID: Cell<Option<TaskId>> = Cell::new(None);
@@ -26,15 +29,15 @@
}
/// Spawns a future on the executor.
-fn spawn<F, R>(future: F) -> async_task::JoinHandle<R, TaskId>
+fn spawn<F, R>(future: F) -> JoinHandle<R>
where
F: Future<Output = R> + Send + 'static,
R: Send + 'static,
{
lazy_static! {
// A channel that holds scheduled tasks.
- static ref QUEUE: Sender<async_task::Task<TaskId>> = {
- let (sender, receiver) = unbounded::<async_task::Task<TaskId>>();
+ static ref QUEUE: Sender<Task> = {
+ let (sender, receiver) = unbounded::<Task>();
// Start the executor thread.
thread::spawn(|| {