1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use futures::Future;

pub trait Spawner<T> {
    type SpawnHandle: Future<Output=T> + Send;
    fn spawn<F: Future<Output=T> + Send + 'static>(f: F) -> Self::SpawnHandle;
}

pub trait Blocker {
    fn block_on<T, F: Future<Output=T>>(f: F) -> T;
}

#[cfg(feature = "use-async-std")]
pub mod use_async_std {
    use super::*;
    use async_std::task::{spawn, block_on, JoinHandle};
    pub struct AsyncStd;

    impl<T: Send + 'static> Spawner<T> for AsyncStd {
        type SpawnHandle = JoinHandle<T>;

        fn spawn<F: Future<Output=T> + Send + 'static>(f: F) -> Self::SpawnHandle {
            spawn(f)
        }
    }
    impl Blocker for AsyncStd {
        fn block_on<T, F: Future<Output=T>>(f: F) -> T {
            block_on(f)
        }
    }
}


cfg_tokio! {

    pub mod use_tokio {
        use super::*;
        use tokio::task as tokio_task;
        pub struct Tokio;
        use std::pin::Pin;

        impl<T: Send + 'static> Spawner<T> for Tokio {
            type SpawnHandle = Pin<Box<dyn Future<Output=T> + Send>>;

            fn spawn<F: Future<Output=T> + Send + 'static>(f: F) -> Self::SpawnHandle {
                let handle = tokio_task::spawn(f);
                Box::pin(async {
                    handle.await.unwrap()
                })
            }
        }
        impl Blocker for Tokio {
            fn block_on<T, F: Future<Output=T>>(f: F) -> T {
                tokio_task::block_in_place(|| {
                    tokio::runtime::Builder::new_current_thread()
                        .build()
                        .unwrap()
                        .block_on(f)
                })
            }
        }
    }
}