future_utils/
thread_future.rs

1use futures::{Future, Async};
2use futures::sync::oneshot;
3use std::{thread, panic};
4use void::Void;
5
6/// Wraps a synchronous function into a future by running it in its own thread. Created using
7/// `thread_future`.
8pub struct ThreadFuture<R> {
9    join_handle: Option<thread::JoinHandle<()>>,
10    rx: oneshot::Receiver<R>,
11}
12
13/// Run a synchronous function in a separate thread and return its result as a `Future`.
14///
15/// # Note
16///
17/// If the given function panics then so will this future.
18pub fn thread_future<F, R>(f: F) -> ThreadFuture<R>
19where
20    R: Send + 'static,
21    F: FnOnce() -> R + Send + 'static
22{
23    let (tx, rx) = oneshot::channel();
24    let join_handle = Some(thread::spawn(|| {
25        let x = f();
26        let _ = tx.send(x);
27    }));
28    ThreadFuture {
29        rx,
30        join_handle,
31    }
32}
33
34impl<R> Future for ThreadFuture<R> {
35    type Item = R;
36    type Error = Void;
37
38    fn poll(&mut self) -> Result<Async<R>, Void> {
39        match self.rx.poll() {
40            Ok(x) => Ok(x),
41            Err(oneshot::Canceled) => {
42                // The thread must have died. Get the error.
43                match unwrap!(self.join_handle.take()).join() {
44                    Ok(()) => unreachable!(),
45                    Err(e) => panic::resume_unwind(e),
46                }
47            },
48        }
49    }
50}
51