1 //! A simple single-threaded executor.
2
3 use std::future::Future;
4 use std::panic::catch_unwind;
5 use std::thread;
6
7 use async_task::{Runnable, Task};
8 use once_cell::sync::Lazy;
9 use smol::future;
10
11 /// Spawns a future on the executor.
spawn<F, T>(future: F) -> Task<T> where F: Future<Output = T> + Send + 'static, T: Send + 'static,12 fn spawn<F, T>(future: F) -> Task<T>
13 where
14 F: Future<Output = T> + Send + 'static,
15 T: Send + 'static,
16 {
17 // A queue that holds scheduled tasks.
18 static QUEUE: Lazy<flume::Sender<Runnable>> = Lazy::new(|| {
19 let (sender, receiver) = flume::unbounded::<Runnable>();
20
21 // Start the executor thread.
22 thread::spawn(|| {
23 for runnable in receiver {
24 // Ignore panics inside futures.
25 let _ignore_panic = catch_unwind(|| runnable.run());
26 }
27 });
28
29 sender
30 });
31
32 // Create a task that is scheduled by pushing it into the queue.
33 let schedule = |runnable| QUEUE.send(runnable).unwrap();
34 let (runnable, task) = async_task::spawn(future, schedule);
35
36 // Schedule the task by pushing it into the queue.
37 runnable.schedule();
38
39 task
40 }
41
main()42 fn main() {
43 // Spawn a future and await its result.
44 let task = spawn(async {
45 println!("Hello, world!");
46 });
47 future::block_on(task);
48 }
49