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