//! A simple single-threaded executor that can spawn non-`Send` futures.
use std::cell::Cell; use std::future::Future; use std::rc::Rc;
use async_task::{Runnable, Task};
thread_local! { // A queue that holds scheduled tasks. static QUEUE: (flume::Sender<Runnable>, flume::Receiver<Runnable>) = flume::unbounded();
}
/// Spawns a future on the executor. fn spawn<F, T>(future: F) -> Task<T> where
F: Future<Output = T> + 'static,
T: 'static,
{ // Create a task that is scheduled by pushing itself into the queue. let schedule = |runnable| QUEUE.with(|(s, _)| s.send(runnable).unwrap()); let (runnable, task) = async_task::spawn_local(future, schedule);
// Schedule the task by pushing it into the queue.
runnable.schedule();
task
}
/// Runs a future to completion. fn run<F, T>(future: F) -> T where
F: Future<Output = T> + 'static,
T: 'static,
{ // Spawn a task that sends its result through a channel. let (s, r) = flume::unbounded();
spawn(asyncmove { drop(s.send(future.await)) }).detach();
loop { // If the original task has completed, return its result. iflet 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(); asyncmove { // Spawn a future that increments the value. let task = spawn({ let val = val.clone(); asyncmove {
val.set(dbg!(val.get()) + 1);
}
});
val.set(dbg!(val.get()) + 1);
task.await;
}
});
// The value should be 2 at the end of the program.
dbg!(val.get());
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet am 2026-06-20)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.