| //! A simple single-threaded executor. |
| |
| use std::future::Future; |
| use std::panic::catch_unwind; |
| use std::thread; |
| |
| use async_task::{Runnable, Task}; |
| use once_cell::sync::Lazy; |
| use smol::future; |
| |
| /// Spawns a future on the executor. |
| fn spawn<F, T>(future: F) -> Task<T> |
| where |
| F: Future<Output = T> + Send + 'static, |
| T: Send + 'static, |
| { |
| // A queue that holds scheduled tasks. |
| static QUEUE: Lazy<flume::Sender<Runnable>> = Lazy::new(|| { |
| let (sender, receiver) = flume::unbounded::<Runnable>(); |
| |
| // Start the executor thread. |
| thread::spawn(|| { |
| for runnable in receiver { |
| // Ignore panics inside futures. |
| let _ignore_panic = catch_unwind(|| runnable.run()); |
| } |
| }); |
| |
| sender |
| }); |
| |
| // Create a task that is scheduled by pushing it into the queue. |
| let schedule = |runnable| QUEUE.send(runnable).unwrap(); |
| let (runnable, task) = async_task::spawn(future, schedule); |
| |
| // Schedule the task by pushing it into the queue. |
| runnable.schedule(); |
| |
| task |
| } |
| |
| fn main() { |
| // Spawn a future and await its result. |
| let task = spawn(async { |
| println!("Hello, world!"); |
| }); |
| future::block_on(task); |
| } |