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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! A batteries included runtime for applications using mobc.
//! Mobc does not implement runtime, it simply exports runtime.

pub use runtime::{DefaultExecutor, Runtime, TaskExecutor};

use std::future::Future;
use std::pin::Pin;

// A new type exports the default executor of Tokio..
// pub type DefaultExecutor = DefaultExecutor;

/// A value that executes futures.
/// see [tokio::Executor](https://docs.rs/tokio/0.2.0-alpha.6/tokio/executor/trait.Executor.html)
pub trait Executor: Send + Sync + 'static + Clone {
    /// Spawns a future object to run on this executor.
    ///
    /// `future` is passed to the executor, which will begin running it. The
    /// future may run on the current thread or another thread at the discretion
    /// of the `Executor` implementation.
    fn spawn(&mut self, future: Pin<Box<dyn Future<Output = ()> + Send>>);
}

#[cfg(all(feature = "tokio", not(feature = "async-std")))]
mod runtime {
    use super::*;

    /// Wrapper of the Tokio Runtime
    pub struct Runtime {
        rt: tokio::runtime::Runtime,
        spawner: TaskExecutor,
    }

    impl Runtime {
        /// Creates a new Runtime
        pub fn new() -> Option<Self> {
            Some(Runtime {
                rt: tokio::runtime::Runtime::new().unwrap(),
                spawner: TaskExecutor,
            })
        }

        /// Returns a spawner
        pub fn handle(&self) -> &TaskExecutor {
            &self.spawner
        }

        /// Run a future to completion on the Tokio runtime. This is the
        /// runtime's entry point.
        pub fn block_on<F, T>(&mut self, future: F) -> T
        where
            F: Future<Output = T>,
        {
            self.rt.block_on(future)
        }

        /// Spawn a future onto the Tokio runtime.
        pub fn spawn<F, T>(&self, future: F)
        where
            F: Future<Output = T> + Send + 'static,
            T: Send + 'static,
        {
            self.rt.spawn(future);
        }
    }

    /// Simple handler for spawning task
    #[derive(Clone)]
    pub struct TaskExecutor;

    impl TaskExecutor {
        /// Spawn a future onto the Tokio runtime.
        pub fn spawn<F>(&self, future: F)
        where
            F: Future + Send + 'static,
            F::Output: Send + 'static,
        {
            tokio::spawn(future);
        }
    }

    #[derive(Clone)]
    /// The default executor of tokio.
    pub struct DefaultExecutor;

    impl DefaultExecutor {
        /// The default executor of tokio.
        pub fn current() -> Self {
            Self {}
        }
    }

    impl Executor for DefaultExecutor {
        fn spawn(&mut self, future: Pin<Box<dyn Future<Output = ()> + Send>>) {
            tokio::spawn(future);
        }
    }
}

#[cfg(all(feature = "async-std"))]
mod runtime {
    use super::*;
    use async_std::task;

    #[derive(Clone)]
    pub struct TaskExecutor;

    impl TaskExecutor {
        pub fn spawn<F>(&self, future: F)
        where
            F: Future + Send + 'static,
            F::Output: Send + 'static,
        {
            task::spawn(future);
        }
    }

    pub struct Runtime(TaskExecutor);

    impl Runtime {
        pub fn new() -> Option<Self> {
            Some(Runtime(TaskExecutor))
        }

        pub fn handle(&self) -> &TaskExecutor {
            &self.0
        }

        pub fn block_on<F, T>(&mut self, future: F) -> T
        where
            F: Future<Output = T>,
        {
            task::block_on(future)
        }

        pub fn spawn<F, T>(&self, future: F)
        where
            F: Future<Output = T> + Send + 'static,
            T: Send + 'static,
        {
            task::spawn(future);
        }
    }

    #[derive(Clone)]
    pub struct DefaultExecutor;

    impl DefaultExecutor {
        pub fn current() -> Self {
            Self {}
        }
    }

    impl Executor for DefaultExecutor {
        fn spawn(&mut self, future: Pin<Box<dyn Future<Output = ()> + Send>>) {
            task::spawn(future);
        }
    }
}