xref: /aosp_15_r20/external/crosvm/base/src/sys/windows/events.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker pub use super::wait::*;
6*bb4ee6a4SAndroid Build Coastguard Worker use super::RawDescriptor;
7*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
8*bb4ee6a4SAndroid Build Coastguard Worker use crate::EventToken;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker /// Represents descriptor-token pairs which represent an event which can be triggered in the
11*bb4ee6a4SAndroid Build Coastguard Worker /// EventContext
12*bb4ee6a4SAndroid Build Coastguard Worker #[derive(PartialEq, Eq)]
13*bb4ee6a4SAndroid Build Coastguard Worker pub struct EventTrigger<T: EventToken> {
14*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) token: T,
15*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) event: RawDescriptor,
16*bb4ee6a4SAndroid Build Coastguard Worker }
17*bb4ee6a4SAndroid Build Coastguard Worker 
18*bb4ee6a4SAndroid Build Coastguard Worker impl<T: EventToken> EventTrigger<T> {
from(descriptor: &dyn AsRawDescriptor, token: T) -> Self19*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from(descriptor: &dyn AsRawDescriptor, token: T) -> Self {
20*bb4ee6a4SAndroid Build Coastguard Worker         EventTrigger {
21*bb4ee6a4SAndroid Build Coastguard Worker             token,
22*bb4ee6a4SAndroid Build Coastguard Worker             event: descriptor.as_raw_descriptor(),
23*bb4ee6a4SAndroid Build Coastguard Worker         }
24*bb4ee6a4SAndroid Build Coastguard Worker     }
25*bb4ee6a4SAndroid Build Coastguard Worker }
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker impl<T: EventToken> Clone for EventTrigger<T> {
clone(&self) -> Self28*bb4ee6a4SAndroid Build Coastguard Worker     fn clone(&self) -> Self {
29*bb4ee6a4SAndroid Build Coastguard Worker         EventTrigger {
30*bb4ee6a4SAndroid Build Coastguard Worker             token: T::from_raw_token(self.token.as_raw_token()),
31*bb4ee6a4SAndroid Build Coastguard Worker             event: self.event,
32*bb4ee6a4SAndroid Build Coastguard Worker         }
33*bb4ee6a4SAndroid Build Coastguard Worker     }
34*bb4ee6a4SAndroid Build Coastguard Worker }
35*bb4ee6a4SAndroid Build Coastguard Worker 
36*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
37*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
38*bb4ee6a4SAndroid Build Coastguard Worker     use std::time::Duration;
39*bb4ee6a4SAndroid Build Coastguard Worker 
40*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
41*bb4ee6a4SAndroid Build Coastguard Worker     use crate::Event;
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
event_context()44*bb4ee6a4SAndroid Build Coastguard Worker     fn event_context() {
45*bb4ee6a4SAndroid Build Coastguard Worker         let evt1 = Event::new().unwrap();
46*bb4ee6a4SAndroid Build Coastguard Worker         let evt2 = Event::new().unwrap();
47*bb4ee6a4SAndroid Build Coastguard Worker         evt1.signal().unwrap();
48*bb4ee6a4SAndroid Build Coastguard Worker         evt2.signal().unwrap();
49*bb4ee6a4SAndroid Build Coastguard Worker         let ctx: EventContext<u32> =
50*bb4ee6a4SAndroid Build Coastguard Worker             EventContext::build_with(&[EventTrigger::from(&evt1, 1), EventTrigger::from(&evt2, 2)])
51*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap();
52*bb4ee6a4SAndroid Build Coastguard Worker 
53*bb4ee6a4SAndroid Build Coastguard Worker         let mut evt_count = 0;
54*bb4ee6a4SAndroid Build Coastguard Worker         while evt_count < 2 {
55*bb4ee6a4SAndroid Build Coastguard Worker             for event in ctx.wait().unwrap().iter() {
56*bb4ee6a4SAndroid Build Coastguard Worker                 evt_count += 1;
57*bb4ee6a4SAndroid Build Coastguard Worker                 match event.token {
58*bb4ee6a4SAndroid Build Coastguard Worker                     1 => {
59*bb4ee6a4SAndroid Build Coastguard Worker                         evt1.wait().unwrap();
60*bb4ee6a4SAndroid Build Coastguard Worker                         ctx.delete(&evt1).unwrap();
61*bb4ee6a4SAndroid Build Coastguard Worker                     }
62*bb4ee6a4SAndroid Build Coastguard Worker                     2 => {
63*bb4ee6a4SAndroid Build Coastguard Worker                         evt2.wait().unwrap();
64*bb4ee6a4SAndroid Build Coastguard Worker                         ctx.delete(&evt2).unwrap();
65*bb4ee6a4SAndroid Build Coastguard Worker                     }
66*bb4ee6a4SAndroid Build Coastguard Worker                     _ => panic!("unexpected token"),
67*bb4ee6a4SAndroid Build Coastguard Worker                 };
68*bb4ee6a4SAndroid Build Coastguard Worker             }
69*bb4ee6a4SAndroid Build Coastguard Worker         }
70*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(evt_count, 2);
71*bb4ee6a4SAndroid Build Coastguard Worker     }
72*bb4ee6a4SAndroid Build Coastguard Worker 
73*bb4ee6a4SAndroid Build Coastguard Worker     // TODO(145170451) rizhang: This test will be needed to be implemented when the round robn
74*bb4ee6a4SAndroid Build Coastguard Worker     // implementation is complete
75*bb4ee6a4SAndroid Build Coastguard Worker     // #[test]
76*bb4ee6a4SAndroid Build Coastguard Worker     // fn poll_context_overflow() {
77*bb4ee6a4SAndroid Build Coastguard Worker     //     const EVT_COUNT: usize = MAXIMUM_WAIT_OBJECTS * 2 + 1;
78*bb4ee6a4SAndroid Build Coastguard Worker     //     let ctx: EventContext<usize> = EventContext::new().unwrap();
79*bb4ee6a4SAndroid Build Coastguard Worker     //     let mut evts = Vec::with_capacity(EVT_COUNT);
80*bb4ee6a4SAndroid Build Coastguard Worker     //     for i in 0..EVT_COUNT {
81*bb4ee6a4SAndroid Build Coastguard Worker     //         let evt = Event::new().unwrap();
82*bb4ee6a4SAndroid Build Coastguard Worker     //         evt.signal().unwrap();
83*bb4ee6a4SAndroid Build Coastguard Worker     //         ctx.add(&evt, i).unwrap();
84*bb4ee6a4SAndroid Build Coastguard Worker     //         evts.push(evt);
85*bb4ee6a4SAndroid Build Coastguard Worker     //     }
86*bb4ee6a4SAndroid Build Coastguard Worker     //     let mut evt_count = 0;
87*bb4ee6a4SAndroid Build Coastguard Worker     //     while evt_count < EVT_COUNT {
88*bb4ee6a4SAndroid Build Coastguard Worker     //         for event in ctx.wait().unwrap().iter_readable() {
89*bb4ee6a4SAndroid Build Coastguard Worker     //             evts[event.token()].wait().unwrap();
90*bb4ee6a4SAndroid Build Coastguard Worker     //             evt_count += 1;
91*bb4ee6a4SAndroid Build Coastguard Worker     //         }
92*bb4ee6a4SAndroid Build Coastguard Worker     //     }
93*bb4ee6a4SAndroid Build Coastguard Worker     // }
94*bb4ee6a4SAndroid Build Coastguard Worker 
95*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
poll_context_timeout()96*bb4ee6a4SAndroid Build Coastguard Worker     fn poll_context_timeout() {
97*bb4ee6a4SAndroid Build Coastguard Worker         let ctx: EventContext<u32> = EventContext::new().unwrap();
98*bb4ee6a4SAndroid Build Coastguard Worker         let evt = Event::new().unwrap();
99*bb4ee6a4SAndroid Build Coastguard Worker         ctx.add(EventTrigger::from(&evt, 1))
100*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to add event.");
101*bb4ee6a4SAndroid Build Coastguard Worker         let dur = Duration::from_millis(100);
102*bb4ee6a4SAndroid Build Coastguard Worker         let events = ctx.wait_timeout(dur).unwrap();
103*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(events.len(), 0);
104*bb4ee6a4SAndroid Build Coastguard Worker     }
105*bb4ee6a4SAndroid Build Coastguard Worker 
106*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
wait_returns_mulitple_signal_events()107*bb4ee6a4SAndroid Build Coastguard Worker     fn wait_returns_mulitple_signal_events() {
108*bb4ee6a4SAndroid Build Coastguard Worker         let evt1 = Event::new().unwrap();
109*bb4ee6a4SAndroid Build Coastguard Worker         let evt2 = Event::new().unwrap();
110*bb4ee6a4SAndroid Build Coastguard Worker         let evt3 = Event::new().unwrap();
111*bb4ee6a4SAndroid Build Coastguard Worker         evt1.signal().expect("Failed to write to event.");
112*bb4ee6a4SAndroid Build Coastguard Worker         evt2.signal().expect("Failed to write to event.");
113*bb4ee6a4SAndroid Build Coastguard Worker         evt3.signal().expect("Failed to write to event.");
114*bb4ee6a4SAndroid Build Coastguard Worker         let ctx: EventContext<u32> = EventContext::build_with(&[
115*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt1, 1),
116*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt2, 2),
117*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt3, 3),
118*bb4ee6a4SAndroid Build Coastguard Worker         ])
119*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
120*bb4ee6a4SAndroid Build Coastguard Worker         let events = ctx.wait().unwrap();
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker         let tokens: Vec<u32> = events.iter().map(|e| e.token).collect();
123*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(tokens.len(), 3);
124*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(tokens, [1, 2, 3]);
125*bb4ee6a4SAndroid Build Coastguard Worker     }
126*bb4ee6a4SAndroid Build Coastguard Worker 
127*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
wait_returns_mulitple_signal_and_unsignaled_events()128*bb4ee6a4SAndroid Build Coastguard Worker     fn wait_returns_mulitple_signal_and_unsignaled_events() {
129*bb4ee6a4SAndroid Build Coastguard Worker         let evt1 = Event::new().unwrap();
130*bb4ee6a4SAndroid Build Coastguard Worker         let evt2 = Event::new().unwrap();
131*bb4ee6a4SAndroid Build Coastguard Worker         let evt3 = Event::new().unwrap();
132*bb4ee6a4SAndroid Build Coastguard Worker         let evt4 = Event::new().unwrap();
133*bb4ee6a4SAndroid Build Coastguard Worker         let evt5 = Event::new().unwrap();
134*bb4ee6a4SAndroid Build Coastguard Worker         let evt6 = Event::new().unwrap();
135*bb4ee6a4SAndroid Build Coastguard Worker         let evt7 = Event::new().unwrap();
136*bb4ee6a4SAndroid Build Coastguard Worker         evt1.signal().unwrap();
137*bb4ee6a4SAndroid Build Coastguard Worker         evt2.signal().unwrap();
138*bb4ee6a4SAndroid Build Coastguard Worker         evt4.signal().unwrap();
139*bb4ee6a4SAndroid Build Coastguard Worker         evt7.signal().unwrap();
140*bb4ee6a4SAndroid Build Coastguard Worker         let ctx: EventContext<u32> = EventContext::build_with(&[
141*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt1, 1),
142*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt2, 2),
143*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt3, 3),
144*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt4, 4),
145*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt5, 5),
146*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt6, 6),
147*bb4ee6a4SAndroid Build Coastguard Worker             EventTrigger::from(&evt7, 7),
148*bb4ee6a4SAndroid Build Coastguard Worker         ])
149*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
150*bb4ee6a4SAndroid Build Coastguard Worker         let events = ctx.wait().unwrap();
151*bb4ee6a4SAndroid Build Coastguard Worker 
152*bb4ee6a4SAndroid Build Coastguard Worker         let tokens: Vec<u32> = events.iter().map(|e| e.token).collect();
153*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(tokens.len(), 4);
154*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(tokens, [1, 2, 4, 7]);
155*bb4ee6a4SAndroid Build Coastguard Worker     }
156*bb4ee6a4SAndroid Build Coastguard Worker }
157