xref: /aosp_15_r20/external/crosvm/base/src/wait_context.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2020 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::time::Duration;
6 
7 pub use base_event_token_derive::*;
8 use smallvec::SmallVec;
9 
10 use crate::descriptor::AsRawDescriptor;
11 use crate::platform::EventContext;
12 use crate::RawDescriptor;
13 use crate::Result;
14 
15 /// Trait that can be used to associate events with arbitrary enums when using
16 /// `WaitContext`.
17 ///
18 /// Simple enums that have no or primitive variant data data can use the `#[derive(EventToken)]`
19 /// custom derive to implement this trait. See
20 /// [event_token_derive::event_token](../base_event_token_derive/fn.event_token.html) for details.
21 pub trait EventToken {
22     /// Converts this token into a u64 that can be turned back into a token via `from_raw_token`.
as_raw_token(&self) -> u6423     fn as_raw_token(&self) -> u64;
24 
25     /// Converts a raw token as returned from `as_raw_token` back into a token.
26     ///
27     /// It is invalid to give a raw token that was not returned via `as_raw_token` from the same
28     /// `Self`. The implementation can expect that this will never happen as a result of its usage
29     /// in `WaitContext`.
from_raw_token(data: u64) -> Self30     fn from_raw_token(data: u64) -> Self;
31 }
32 
33 impl EventToken for usize {
as_raw_token(&self) -> u6434     fn as_raw_token(&self) -> u64 {
35         *self as u64
36     }
37 
from_raw_token(data: u64) -> Self38     fn from_raw_token(data: u64) -> Self {
39         data as Self
40     }
41 }
42 
43 impl EventToken for u64 {
as_raw_token(&self) -> u6444     fn as_raw_token(&self) -> u64 {
45         *self
46     }
47 
from_raw_token(data: u64) -> Self48     fn from_raw_token(data: u64) -> Self {
49         data as Self
50     }
51 }
52 
53 impl EventToken for u32 {
as_raw_token(&self) -> u6454     fn as_raw_token(&self) -> u64 {
55         u64::from(*self)
56     }
57 
from_raw_token(data: u64) -> Self58     fn from_raw_token(data: u64) -> Self {
59         data as Self
60     }
61 }
62 
63 impl EventToken for u16 {
as_raw_token(&self) -> u6464     fn as_raw_token(&self) -> u64 {
65         u64::from(*self)
66     }
67 
from_raw_token(data: u64) -> Self68     fn from_raw_token(data: u64) -> Self {
69         data as Self
70     }
71 }
72 
73 impl EventToken for u8 {
as_raw_token(&self) -> u6474     fn as_raw_token(&self) -> u64 {
75         u64::from(*self)
76     }
77 
from_raw_token(data: u64) -> Self78     fn from_raw_token(data: u64) -> Self {
79         data as Self
80     }
81 }
82 
83 impl EventToken for () {
as_raw_token(&self) -> u6484     fn as_raw_token(&self) -> u64 {
85         0
86     }
87 
from_raw_token(_data: u64) -> Self88     fn from_raw_token(_data: u64) -> Self {}
89 }
90 
91 /// Represents an event that has been signaled and waited for via a wait function.
92 #[derive(Copy, Clone, Debug)]
93 pub struct TriggeredEvent<T: EventToken> {
94     pub token: T,
95     pub is_readable: bool,
96     pub is_writable: bool,
97     pub is_hungup: bool,
98 }
99 
100 /// Represents types of events to watch for.
101 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
102 pub enum EventType {
103     // Used to to temporarily stop waiting for events without
104     // removing the associated descriptor from the WaitContext.
105     // In most cases if a descriptor no longer needs to be
106     // waited on, prefer removing it entirely with
107     // WaitContext#delete
108     None,
109     Read,
110     Write,
111     ReadWrite,
112 }
113 
114 /// Used to wait for multiple objects which are eligible for waiting.
115 ///
116 /// # Example
117 ///
118 /// ```
119 /// use base::{Event, EventToken, Result, WaitContext};
120 ///
121 /// #[derive(EventToken, Copy, Clone, Debug, PartialEq, Eq)]
122 /// enum ExampleToken {
123 ///    SomeEvent(u32),
124 ///    AnotherEvent,
125 /// }
126 ///
127 /// let evt1 = Event::new()?;
128 /// let evt2 = Event::new()?;
129 /// let another_evt = Event::new()?;
130 ///
131 /// let ctx: WaitContext<ExampleToken> = WaitContext::build_with(&[
132 ///     (&evt1, ExampleToken::SomeEvent(1)),
133 ///     (&evt2, ExampleToken::SomeEvent(2)),
134 ///     (&another_evt, ExampleToken::AnotherEvent),
135 /// ])?;
136 ///
137 /// // Trigger one of the `SomeEvent` events.
138 /// evt2.signal()?;
139 ///
140 /// // Wait for an event to fire. `wait()` will return immediately in this example because `evt2`
141 /// // has already been triggered, but in normal use, `wait()` will block until at least one event
142 /// // is signaled by another thread or process.
143 /// let events = ctx.wait()?;
144 /// let tokens: Vec<ExampleToken> = events.iter().filter(|e| e.is_readable)
145 ///     .map(|e| e.token).collect();
146 /// assert_eq!(tokens, [ExampleToken::SomeEvent(2)]);
147 ///
148 /// // Reset evt2 so it doesn't trigger again in the next `wait()` call.
149 /// let _ = evt2.reset()?;
150 ///
151 /// // Trigger a different event.
152 /// another_evt.signal()?;
153 ///
154 /// let events = ctx.wait()?;
155 /// let tokens: Vec<ExampleToken> = events.iter().filter(|e| e.is_readable)
156 ///     .map(|e| e.token).collect();
157 /// assert_eq!(tokens, [ExampleToken::AnotherEvent]);
158 ///
159 /// let _ = another_evt.reset()?;
160 /// # Ok::<(), base::Error>(())
161 /// ```
162 pub struct WaitContext<T: EventToken>(pub(crate) EventContext<T>);
163 
164 impl<T: EventToken> WaitContext<T> {
165     /// Creates a new WaitContext.
new() -> Result<WaitContext<T>>166     pub fn new() -> Result<WaitContext<T>> {
167         EventContext::new().map(WaitContext)
168     }
169 
170     /// Creates a new WaitContext with the the associated triggers.
build_with(triggers: &[(&dyn AsRawDescriptor, T)]) -> Result<WaitContext<T>>171     pub fn build_with(triggers: &[(&dyn AsRawDescriptor, T)]) -> Result<WaitContext<T>> {
172         let ctx = WaitContext::new()?;
173         ctx.add_many(triggers)?;
174         Ok(ctx)
175     }
176 
177     /// Adds a trigger to the WaitContext.
add(&self, descriptor: &dyn AsRawDescriptor, token: T) -> Result<()>178     pub fn add(&self, descriptor: &dyn AsRawDescriptor, token: T) -> Result<()> {
179         self.add_for_event(descriptor, EventType::Read, token)
180     }
181 
182     /// Adds a trigger to the WaitContext watching for a specific type of event
add_for_event( &self, descriptor: &dyn AsRawDescriptor, event_type: EventType, token: T, ) -> Result<()>183     pub fn add_for_event(
184         &self,
185         descriptor: &dyn AsRawDescriptor,
186         event_type: EventType,
187         token: T,
188     ) -> Result<()> {
189         self.0.add_for_event(descriptor, event_type, token)
190     }
191 
192     /// Adds multiple triggers to the WaitContext.
add_many(&self, triggers: &[(&dyn AsRawDescriptor, T)]) -> Result<()>193     pub fn add_many(&self, triggers: &[(&dyn AsRawDescriptor, T)]) -> Result<()> {
194         for trigger in triggers {
195             self.add(trigger.0, T::from_raw_token(trigger.1.as_raw_token()))?
196         }
197         Ok(())
198     }
199 
200     /// Modifies a trigger already added to the WaitContext. If the descriptor is
201     /// already registered, its associated token will be updated.
modify( &self, descriptor: &dyn AsRawDescriptor, event_type: EventType, token: T, ) -> Result<()>202     pub fn modify(
203         &self,
204         descriptor: &dyn AsRawDescriptor,
205         event_type: EventType,
206         token: T,
207     ) -> Result<()> {
208         self.0.modify(descriptor, event_type, token)
209     }
210 
211     /// Removes the given handle from triggers registered in the WaitContext if
212     /// present.
delete(&self, descriptor: &dyn AsRawDescriptor) -> Result<()>213     pub fn delete(&self, descriptor: &dyn AsRawDescriptor) -> Result<()> {
214         self.0.delete(descriptor)
215     }
216 
217     /// Waits for one or more of the registered triggers to become signaled.
wait(&self) -> Result<SmallVec<[TriggeredEvent<T>; 16]>>218     pub fn wait(&self) -> Result<SmallVec<[TriggeredEvent<T>; 16]>> {
219         self.wait_timeout(Duration::new(i64::MAX as u64, 0))
220     }
221 
222     /// Waits for one or more of the registered triggers to become signaled, failing if no triggers
223     /// are signaled before the designated timeout has elapsed.
wait_timeout(&self, timeout: Duration) -> Result<SmallVec<[TriggeredEvent<T>; 16]>>224     pub fn wait_timeout(&self, timeout: Duration) -> Result<SmallVec<[TriggeredEvent<T>; 16]>> {
225         self.0.wait_timeout(timeout)
226     }
227 }
228 
229 impl<T: EventToken> AsRawDescriptor for WaitContext<T> {
as_raw_descriptor(&self) -> RawDescriptor230     fn as_raw_descriptor(&self) -> RawDescriptor {
231         self.0.as_raw_descriptor()
232     }
233 }
234 
235 #[cfg(test)]
236 mod tests {
237     use base_event_token_derive::EventToken;
238 
239     use super::*;
240 
241     #[test]
242     #[allow(dead_code)]
event_token_derive()243     fn event_token_derive() {
244         #[derive(EventToken)]
245         enum EmptyToken {}
246 
247         #[derive(PartialEq, Debug, EventToken)]
248         enum Token {
249             Alpha,
250             Beta,
251             // comments
252             Gamma(u32),
253             Delta { index: usize },
254             Omega,
255         }
256 
257         assert_eq!(
258             Token::from_raw_token(Token::Alpha.as_raw_token()),
259             Token::Alpha
260         );
261         assert_eq!(
262             Token::from_raw_token(Token::Beta.as_raw_token()),
263             Token::Beta
264         );
265         assert_eq!(
266             Token::from_raw_token(Token::Gamma(55).as_raw_token()),
267             Token::Gamma(55)
268         );
269         assert_eq!(
270             Token::from_raw_token(Token::Delta { index: 100 }.as_raw_token()),
271             Token::Delta { index: 100 }
272         );
273         assert_eq!(
274             Token::from_raw_token(Token::Omega.as_raw_token()),
275             Token::Omega
276         );
277     }
278 }
279