futures_net/runtime/
mod.rs

1//! Futures Async Execute Engine
2
3//! # Examples
4//! ```rust
5//! use futures_net::runtime::Runtime;
6//!
7//! #[futures_net::main]
8//! async fn main() {
9//!        say_hello().await;
10//! }
11//! async fn say_hello() {
12//!     println!("Hello, futures_net!");
13//! }
14//!
15//! ```
16
17use futures_core::future::{BoxFuture, Future, LocalBoxFuture};
18use futures_executor::{LocalPool, LocalSpawner};
19use futures_util::task::{LocalSpawn as _, Spawn as _};
20
21/// The Runtime for driving the  application.
22pub trait Runtime {
23    /// The value for spawning  cases.
24    type Spawner: Spawner;
25
26    /// Create the instance of `Spawner`.
27    fn spawner(&self) -> Self::Spawner;
28
29    /// Run a future and wait for its result.
30    fn exec<Fut>(&mut self, fut: Fut) -> Fut::Output
31    where
32        Fut: Future;
33}
34
35impl<T: ?Sized> Runtime for &mut T
36where
37    T: Runtime,
38{
39    type Spawner = T::Spawner;
40
41    #[inline]
42    fn spawner(&self) -> Self::Spawner {
43        (**self).spawner()
44    }
45
46    #[inline]
47    fn exec<Fut>(&mut self, fut: Fut) -> Fut::Output
48    where
49        Fut: Future,
50    {
51        (**self).exec(fut)
52    }
53}
54
55impl<T: ?Sized> Runtime for Box<T>
56where
57    T: Runtime,
58{
59    type Spawner = T::Spawner;
60
61    #[inline]
62    fn spawner(&self) -> Self::Spawner {
63        (**self).spawner()
64    }
65
66    #[inline]
67    fn exec<Fut>(&mut self, fut: Fut) -> Fut::Output
68    where
69        Fut: Future,
70    {
71        (**self).exec(fut)
72    }
73}
74
75/// The value for spawning  cases.
76pub trait Spawner {
77    /// Spawn a task to execute a  case.
78    fn spawn(&mut self, fut: BoxFuture<'static, ()>) -> anyhow::Result<()>;
79
80    /// Spawn a task to execute a  case onto the current thread.
81    fn spawn_local(&mut self, fut: LocalBoxFuture<'static, ()>) -> anyhow::Result<()>;
82
83    /// Spawn a task to execute a  case which may block the running thread.
84    fn block(&mut self, f: Box<dyn FnOnce() + Send + 'static>) -> anyhow::Result<()>;
85}
86
87impl<T: ?Sized> Spawner for &mut T
88where
89    T: Spawner,
90{
91    #[inline]
92    fn spawn(&mut self, fut: BoxFuture<'static, ()>) -> anyhow::Result<()> {
93        (**self).spawn(fut)
94    }
95
96    #[inline]
97    fn spawn_local(&mut self, fut: LocalBoxFuture<'static, ()>) -> anyhow::Result<()> {
98        (**self).spawn_local(fut)
99    }
100
101    #[inline]
102    fn block(&mut self, f: Box<dyn FnOnce() + Send + 'static>) -> anyhow::Result<()> {
103        (**self).block(f)
104    }
105}
106
107impl<T: ?Sized> Spawner for Box<T>
108where
109    T: Spawner,
110{
111    #[inline]
112    fn spawn(&mut self, fut: BoxFuture<'static, ()>) -> anyhow::Result<()> {
113        (**self).spawn(fut)
114    }
115
116    #[inline]
117    fn spawn_local(&mut self, fut: LocalBoxFuture<'static, ()>) -> anyhow::Result<()> {
118        (**self).spawn_local(fut)
119    }
120
121    #[inline]
122    fn block(&mut self, f: Box<dyn FnOnce() + Send + 'static>) -> anyhow::Result<()> {
123        (**self).block(f)
124    }
125}
126
127/// Create an instance of `Runtime` used by the default  harness.
128pub fn default() -> impl Runtime {
129    DefaultRuntime {
130        pool: LocalPool::new(),
131    }
132}
133
134struct DefaultRuntime {
135    pool: LocalPool,
136}
137
138struct DefaultSpawner {
139    spawner: LocalSpawner,
140}
141
142impl Runtime for DefaultRuntime {
143    type Spawner = DefaultSpawner;
144
145    #[inline]
146    fn spawner(&self) -> Self::Spawner {
147        DefaultSpawner {
148            spawner: self.pool.spawner(),
149        }
150    }
151
152    #[inline]
153    fn exec<Fut>(&mut self, fut: Fut) -> Fut::Output
154    where
155        Fut: Future,
156    {
157        self.pool.run_until(fut)
158    }
159}
160
161impl Spawner for DefaultSpawner {
162    fn spawn(&mut self, fut: BoxFuture<'static, ()>) -> anyhow::Result<()> {
163        self.spawner.spawn_obj(fut.into()).map_err(Into::into)
164    }
165
166    fn spawn_local(&mut self, fut: LocalBoxFuture<'static, ()>) -> anyhow::Result<()> {
167        self.spawner.spawn_local_obj(fut.into()).map_err(Into::into)
168    }
169
170    fn block(&mut self, f: Box<dyn FnOnce() + Send + 'static>) -> anyhow::Result<()> {
171        self.spawn_local(Box::pin(async move { f() }))
172    }
173}