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;
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 pub async fn execute<F: Future>(&self, f: F) -> F::Output {
45 let waker = self.runtime.waker();
46 let mut context = Context::from_waker(&waker);
47 let mut future = std::pin::pin!(f);
48 loop {
49 if let Poll::Ready(result) = self.runtime.enter(|| future.as_mut().poll(&mut context)) {
50 self.runtime.enter(|| self.runtime.run());
51 return result;
52 }
53
54 let mut remaining_tasks = self.runtime.enter(|| self.runtime.run());
55
56 remaining_tasks |= self.runtime.flush();
57
58 let timeout = if remaining_tasks {
59 Some(Duration::ZERO)
60 } else {
61 self.runtime.current_timeout()
62 };
63
64 match self.runtime.wait(timeout).await {
65 Ok(_) => {}
66 Err(e)
67 if matches!(
68 e.kind(),
69 io::ErrorKind::TimedOut | io::ErrorKind::Interrupted
70 ) => {}
71 Err(e) => panic!("failed to wait for driver: {e:?}"),
72 }
73
74 if let Err(e) = self.runtime.clear() {
75 error!("failed to clear notifier: {e:?}");
76 }
77
78 self.runtime.poll_with(Some(Duration::ZERO));
79 }
80 }
81}
82
83impl<A: Adapter> Deref for RuntimeCompat<A> {
84 type Target = Runtime;
85
86 fn deref(&self) -> &Self::Target {
87 &self.runtime
88 }
89}