futures_net/runtime/
mod.rs1use futures_core::future::{BoxFuture, Future, LocalBoxFuture};
18use futures_executor::{LocalPool, LocalSpawner};
19use futures_util::task::{LocalSpawn as _, Spawn as _};
20
21pub trait Runtime {
23 type Spawner: Spawner;
25
26 fn spawner(&self) -> Self::Spawner;
28
29 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
75pub trait Spawner {
77 fn spawn(&mut self, fut: BoxFuture<'static, ()>) -> anyhow::Result<()>;
79
80 fn spawn_local(&mut self, fut: LocalBoxFuture<'static, ()>) -> anyhow::Result<()>;
82
83 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
127pub 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}