1#![cfg_attr(docsrs, feature(doc_cfg))]
8#![warn(missing_docs)]
9#![deny(rustdoc::broken_intra_doc_links)]
10#![doc(
11 html_logo_url = "https://github.com/compio-rs/compio-logo/raw/refs/heads/master/generated/colored-bold.svg"
12)]
13#![doc(
14 html_favicon_url = "https://github.com/compio-rs/compio-logo/raw/refs/heads/master/generated/colored-bold.svg"
15)]
16
17use std::{
18 io,
19 ops::Deref,
20 task::{Context, Poll},
21 time::Duration,
22};
23
24use compio_log::error;
25use compio_runtime::{Runtime, SpawnMeta, console};
26use mod_use::mod_use;
27
28mod_use![sys];
29
30pub struct RuntimeCompat<A> {
33 runtime: A,
34}
35
36impl<A: Adapter> RuntimeCompat<A> {
37 pub fn new(runtime: Runtime) -> io::Result<Self> {
39 let runtime = A::new(runtime)?;
40 Ok(Self { runtime })
41 }
42
43 #[track_caller]
48 pub fn execute<F: Future>(&self, f: F) -> impl Future<Output = F::Output> {
49 let f = console::instrument_execute(SpawnMeta::capture().named("execute"), f);
54
55 self.drive(f)
56 }
57
58 async fn drive<F: Future>(&self, f: F) -> F::Output {
59 let waker = self.runtime.waker();
60 let mut context = Context::from_waker(&waker);
61 let mut future = std::pin::pin!(f);
62 loop {
63 if let Poll::Ready(result) = self.runtime.enter(|| future.as_mut().poll(&mut context)) {
64 self.runtime.enter(|| self.runtime.run());
65 return result;
66 }
67
68 let mut remaining_tasks = self.runtime.enter(|| self.runtime.run());
69
70 remaining_tasks |= self.runtime.flush();
71
72 let timeout = if remaining_tasks {
73 Some(Duration::ZERO)
74 } else {
75 self.runtime.current_timeout()
76 };
77
78 match self.runtime.wait(timeout).await {
79 Ok(_) => {}
80 Err(e)
81 if matches!(
82 e.kind(),
83 io::ErrorKind::TimedOut | io::ErrorKind::Interrupted
84 ) => {}
85 Err(e) => panic!("failed to wait for driver: {e:?}"),
86 }
87
88 if let Err(e) = self.runtime.clear() {
89 error!("failed to clear notifier: {e:?}");
90 }
91
92 self.runtime.poll_with(Some(Duration::ZERO));
93 }
94 }
95}
96
97impl<A: Adapter> Deref for RuntimeCompat<A> {
98 type Target = Runtime;
99
100 fn deref(&self) -> &Self::Target {
101 &self.runtime
102 }
103}