1#![warn(missing_docs)]
8
9use inspect::Inspect;
10use pal_async::driver::Driver;
11use pal_async::task::Spawn;
12use pal_async::task::TaskMetadata;
13use std::fmt::Debug;
14use std::pin::Pin;
15use std::sync::Arc;
16
17#[derive(Clone)]
25pub struct VmTaskDriverSource {
26 backend: Arc<dyn DynVmBackend>,
27}
28
29impl VmTaskDriverSource {
30 pub fn new(backend: impl 'static + BuildVmTaskDriver) -> Self {
32 Self {
33 backend: Arc::new(backend),
34 }
35 }
36
37 pub fn simple(&self) -> VmTaskDriver {
41 self.builder().build("")
44 }
45
46 pub fn builder(&self) -> VmTaskDriverBuilder<'_> {
48 VmTaskDriverBuilder {
49 backend: self.backend.as_ref(),
50 run_on_target: false,
51 target_vp: None,
52 }
53 }
54}
55
56pub trait BuildVmTaskDriver: Send + Sync {
58 type Driver: TargetedDriver;
60
61 fn build(&self, name: String, target_vp: Option<u32>, run_on_target: bool) -> Self::Driver;
63}
64
65pub trait TargetedDriver: 'static + Send + Sync + Inspect {
67 fn spawner(&self) -> &dyn Spawn;
69 fn driver(&self) -> &dyn Driver;
71 fn retarget_vp(&self, target_vp: u32);
73 fn is_target_vp_ready(&self) -> bool {
78 true
79 }
80 fn wait_target_vp_ready(&self) -> impl std::future::Future<Output = ()> + Send {
82 std::future::ready(())
83 }
84}
85
86trait DynTargetedDriver: 'static + Send + Sync + Inspect {
87 fn spawner(&self) -> &dyn Spawn;
88 fn driver(&self) -> &dyn Driver;
89 fn retarget_vp(&self, target_vp: u32);
90 fn is_ready(&self) -> bool;
91 fn wait_ready(&self) -> Pin<Box<dyn '_ + std::future::Future<Output = ()> + Send>>;
92}
93
94impl<T: TargetedDriver> DynTargetedDriver for T {
95 fn spawner(&self) -> &dyn Spawn {
96 self.spawner()
97 }
98
99 fn driver(&self) -> &dyn Driver {
100 self.driver()
101 }
102
103 fn retarget_vp(&self, target_vp: u32) {
104 self.retarget_vp(target_vp)
105 }
106
107 fn is_ready(&self) -> bool {
108 self.is_target_vp_ready()
109 }
110
111 fn wait_ready(&self) -> Pin<Box<dyn '_ + std::future::Future<Output = ()> + Send>> {
112 Box::pin(self.wait_target_vp_ready())
113 }
114}
115
116trait DynVmBackend: Send + Sync {
117 fn build(
118 &self,
119 name: String,
120 target_vp: Option<u32>,
121 run_on_target: bool,
122 ) -> Arc<dyn DynTargetedDriver>;
123}
124
125impl<T: BuildVmTaskDriver> DynVmBackend for T {
126 fn build(
127 &self,
128 name: String,
129 target_vp: Option<u32>,
130 run_on_target: bool,
131 ) -> Arc<dyn DynTargetedDriver> {
132 Arc::new(self.build(name, target_vp, run_on_target))
133 }
134}
135
136pub struct VmTaskDriverBuilder<'a> {
138 backend: &'a dyn DynVmBackend,
139 run_on_target: bool,
140 target_vp: Option<u32>,
141}
142
143impl VmTaskDriverBuilder<'_> {
144 pub fn run_on_target(&mut self, run_on_target: bool) -> &mut Self {
154 self.run_on_target = run_on_target;
155 self
156 }
157
158 pub fn target_vp(&mut self, target_vp: u32) -> &mut Self {
164 self.target_vp = Some(target_vp);
165 self
166 }
167
168 pub fn build(&self, name: impl Into<String>) -> VmTaskDriver {
173 VmTaskDriver {
174 inner: self
175 .backend
176 .build(name.into(), self.target_vp, self.run_on_target),
177 }
178 }
179}
180
181#[derive(Clone, Inspect)]
185pub struct VmTaskDriver {
186 #[inspect(flatten)]
187 inner: Arc<dyn DynTargetedDriver>,
188}
189
190impl VmTaskDriver {
191 pub fn retarget_vp(&self, target_vp: u32) {
193 self.inner.retarget_vp(target_vp)
194 }
195
196 pub fn is_target_vp_ready(&self) -> bool {
201 self.inner.is_ready()
202 }
203
204 pub async fn wait_target_vp_ready(&self) {
206 self.inner.wait_ready().await
207 }
208}
209
210impl Driver for VmTaskDriver {
211 fn new_dyn_timer(&self) -> pal_async::driver::PollImpl<dyn pal_async::timer::PollTimer> {
212 self.inner.driver().new_dyn_timer()
213 }
214
215 #[cfg(unix)]
216 fn new_dyn_fd_ready(
217 &self,
218 fd: std::os::fd::RawFd,
219 ) -> std::io::Result<pal_async::driver::PollImpl<dyn pal_async::fd::PollFdReady>> {
220 self.inner.driver().new_dyn_fd_ready(fd)
221 }
222
223 #[cfg(unix)]
224 fn new_dyn_socket_ready(
225 &self,
226 socket: std::os::fd::RawFd,
227 ) -> std::io::Result<pal_async::driver::PollImpl<dyn pal_async::socket::PollSocketReady>> {
228 self.inner.driver().new_dyn_socket_ready(socket)
229 }
230
231 #[cfg(windows)]
232 fn new_dyn_socket_ready(
233 &self,
234 socket: std::os::windows::io::RawSocket,
235 ) -> std::io::Result<pal_async::driver::PollImpl<dyn pal_async::socket::PollSocketReady>> {
236 self.inner.driver().new_dyn_socket_ready(socket)
237 }
238
239 #[cfg(unix)]
240 fn new_dyn_wait(
241 &self,
242 fd: std::os::fd::RawFd,
243 read_size: usize,
244 ) -> std::io::Result<pal_async::driver::PollImpl<dyn pal_async::wait::PollWait>> {
245 self.inner.driver().new_dyn_wait(fd, read_size)
246 }
247
248 #[cfg(windows)]
249 fn new_dyn_wait(
250 &self,
251 handle: std::os::windows::io::RawHandle,
252 ) -> std::io::Result<pal_async::driver::PollImpl<dyn pal_async::wait::PollWait>> {
253 self.inner.driver().new_dyn_wait(handle)
254 }
255
256 #[cfg(windows)]
257 unsafe fn new_dyn_overlapped_file(
258 &self,
259 handle: std::os::windows::io::RawHandle,
260 ) -> std::io::Result<
261 pal_async::driver::PollImpl<dyn pal_async::windows::overlapped::IoOverlapped>,
262 > {
263 unsafe { self.inner.driver().new_dyn_overlapped_file(handle) }
265 }
266}
267
268impl Spawn for VmTaskDriver {
269 fn scheduler(&self, metadata: &TaskMetadata) -> Arc<dyn pal_async::task::Schedule> {
270 self.inner.spawner().scheduler(metadata)
271 }
272}
273
274#[derive(Debug)]
276pub struct SingleDriverBackend<T>(T);
277
278impl<T: Driver + Spawn + Clone> SingleDriverBackend<T> {
279 pub fn new(driver: T) -> Self {
282 Self(driver)
283 }
284}
285
286#[derive(Debug)]
288pub struct SingleDriver<T>(T);
289
290impl<T> Inspect for SingleDriver<T> {
291 fn inspect(&self, req: inspect::Request<'_>) {
292 req.ignore();
293 }
294}
295
296impl<T: Driver + Spawn + Clone> BuildVmTaskDriver for SingleDriverBackend<T> {
297 type Driver = SingleDriver<T>;
298
299 fn build(&self, _name: String, _target_vp: Option<u32>, _run_on_target: bool) -> Self::Driver {
300 SingleDriver(self.0.clone())
301 }
302}
303
304impl<T: Driver + Spawn> TargetedDriver for SingleDriver<T> {
305 fn spawner(&self) -> &dyn Spawn {
306 &self.0
307 }
308
309 fn driver(&self) -> &dyn Driver {
310 &self.0
311 }
312
313 fn retarget_vp(&self, _target_vp: u32) {}
314}
315
316pub mod thread {
317 use super::BuildVmTaskDriver;
321 use super::TargetedDriver;
322 use inspect::Inspect;
323 use pal_async::DefaultDriver;
324 use pal_async::DefaultPool;
325 use pal_async::driver::Driver;
326 use pal_async::task::Spawn;
327
328 #[derive(Debug)]
335 pub struct ThreadDriverBackend {
336 default_driver: DefaultDriver,
337 }
338
339 impl ThreadDriverBackend {
340 pub fn new(default_driver: DefaultDriver) -> Self {
343 Self { default_driver }
344 }
345 }
346
347 impl BuildVmTaskDriver for ThreadDriverBackend {
348 type Driver = ThreadDriver;
349
350 fn build(
351 &self,
352 name: String,
353 target_vp: Option<u32>,
354 _run_on_target: bool,
355 ) -> Self::Driver {
356 if target_vp.is_some() {
358 let (_, driver) = DefaultPool::spawn_on_thread(name);
359 ThreadDriver {
360 inner: driver,
361 has_dedicated_thread: true,
362 }
363 } else {
364 ThreadDriver {
365 inner: self.default_driver.clone(),
366 has_dedicated_thread: false,
367 }
368 }
369 }
370 }
371
372 #[derive(Debug, Inspect)]
374 pub struct ThreadDriver {
375 #[inspect(skip)]
376 inner: DefaultDriver,
377 has_dedicated_thread: bool,
378 }
379
380 impl TargetedDriver for ThreadDriver {
381 fn spawner(&self) -> &dyn Spawn {
382 &self.inner
383 }
384
385 fn driver(&self) -> &dyn Driver {
386 &self.inner
387 }
388
389 fn retarget_vp(&self, _target_vp: u32) {}
390 }
391}