1use pal_async::driver::SpawnDriver;
5use pal_async::task::Task;
6use pal_async::wait::PolledWait;
7use pal_event::Event;
8use std::io;
9use vmcore::interrupt::Interrupt;
10
11pub trait OsEventBacked {
14 fn os_event(&self) -> Option<&Event>;
16
17 fn signal(&self);
19}
20
21impl OsEventBacked for Interrupt {
22 fn os_event(&self) -> Option<&Event> {
23 self.event()
24 }
25
26 fn signal(&self) {
27 self.deliver();
28 }
29}
30
31pub struct WrappedEvent {
34 _task: Task<()>,
35}
36
37impl WrappedEvent {
38 fn new(
40 driver: &impl SpawnDriver,
41 original: impl OsEventBacked + Send + 'static,
42 ) -> io::Result<(Self, Event)> {
43 let event = Event::new();
44 let wait = PolledWait::new(driver, event.clone())?;
45 let task = driver.spawn("vmbus-event-wrapper", async move {
46 Self::run(wait, original).await;
47 });
48 Ok((Self { _task: task }, event))
49 }
50
51 async fn run(mut event: PolledWait<Event>, original: impl OsEventBacked) {
52 loop {
53 event.wait().await.expect("wait should not fail");
54 original.signal();
55 }
56 }
57}
58
59pub enum MaybeWrappedEvent<T> {
61 Original(T),
62 Wrapped { event: Event, wrapper: WrappedEvent },
63}
64
65impl<T: OsEventBacked + Send + 'static> MaybeWrappedEvent<T> {
66 pub fn new(driver: &impl SpawnDriver, original: T) -> io::Result<Self> {
70 if original.os_event().is_some() {
71 Ok(Self::Original(original))
72 } else {
73 let (wrapper, event) = WrappedEvent::new(driver, original)?;
74 Ok(Self::Wrapped { event, wrapper })
75 }
76 }
77
78 pub fn event(&self) -> &Event {
81 match self {
82 Self::Original(original) => original.os_event().expect("event should be present"),
83 Self::Wrapped { event, .. } => event,
84 }
85 }
86
87 pub fn into_wrapped(self) -> Option<WrappedEvent> {
89 match self {
90 Self::Original(_) => None,
91 Self::Wrapped { wrapper, .. } => Some(wrapper),
92 }
93 }
94}