1 //! A function that runs a future to completion on a dedicated thread.
2
3 use std::future::Future;
4 use std::sync::Arc;
5 use std::thread;
6
7 use async_task::Task;
8 use smol::future;
9
10 /// Spawns a future on a new dedicated thread.
11 ///
12 /// The returned task can be used to await the output of the future.
spawn_on_thread<F, T>(future: F) -> Task<T> where F: Future<Output = T> + Send + 'static, T: Send + 'static,13 fn spawn_on_thread<F, T>(future: F) -> Task<T>
14 where
15 F: Future<Output = T> + Send + 'static,
16 T: Send + 'static,
17 {
18 // Create a channel that holds the task when it is scheduled for running.
19 let (sender, receiver) = flume::unbounded();
20 let sender = Arc::new(sender);
21 let s = Arc::downgrade(&sender);
22
23 // Wrap the future into one that disconnects the channel on completion.
24 let future = async move {
25 // When the inner future completes, the sender gets dropped and disconnects the channel.
26 let _sender = sender;
27 future.await
28 };
29
30 // Create a task that is scheduled by sending it into the channel.
31 let schedule = move |runnable| s.upgrade().unwrap().send(runnable).unwrap();
32 let (runnable, task) = async_task::spawn(future, schedule);
33
34 // Schedule the task by sending it into the channel.
35 runnable.schedule();
36
37 // Spawn a thread running the task to completion.
38 thread::spawn(move || {
39 // Keep taking the task from the channel and running it until completion.
40 for runnable in receiver {
41 runnable.run();
42 }
43 });
44
45 task
46 }
47
main()48 fn main() {
49 // Spawn a future on a dedicated thread.
50 future::block_on(spawn_on_thread(async {
51 println!("Hello, world!");
52 }));
53 }
54