xref: /aosp_15_r20/external/crosvm/base/src/event.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 use serde::Deserialize;
8 use serde::Serialize;
9 
10 use crate::descriptor::AsRawDescriptor;
11 use crate::descriptor::FromRawDescriptor;
12 use crate::descriptor::IntoRawDescriptor;
13 use crate::descriptor::SafeDescriptor;
14 use crate::platform::PlatformEvent;
15 use crate::RawDescriptor;
16 use crate::Result;
17 
18 /// An inter-process event wait/notify mechanism. Loosely speaking: Writes signal the event. Reads
19 /// block until the event is signaled and then clear the signal.
20 ///
21 /// Supports multiple simultaneous writers (i.e. signalers) but only one simultaneous reader (i.e.
22 /// waiter). The behavior of multiple readers is undefined in cross platform code.
23 ///
24 /// Multiple `Event`s can be polled at once via `WaitContext`.
25 ///
26 /// Implementation notes:
27 /// - Uses eventfd on Linux.
28 /// - Uses synchapi event objects on Windows.
29 /// - The `Event` and `WaitContext` APIs together cannot easily be implemented with the same
30 ///   semantics on all platforms. In particular, it is difficult to support multiple readers, so
31 ///   only a single reader is allowed for now. Multiple readers will result in undefined behavior.
32 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
33 #[serde(transparent)]
34 pub struct Event(pub(crate) PlatformEvent);
35 
36 #[derive(PartialEq, Eq, Debug)]
37 pub enum EventWaitResult {
38     /// The `Event` was signaled.
39     Signaled,
40     /// Timeout limit reached.
41     TimedOut,
42 }
43 
44 impl Event {
45     /// Creates new event in an unsignaled state.
new() -> Result<Event>46     pub fn new() -> Result<Event> {
47         PlatformEvent::new().map(Event)
48     }
49 
50     /// Signals the event.
signal(&self) -> Result<()>51     pub fn signal(&self) -> Result<()> {
52         self.0.signal()
53     }
54 
55     /// Blocks until the event is signaled and clears the signal.
56     ///
57     /// It is undefined behavior to wait on an event from multiple threads or processes
58     /// simultaneously.
wait(&self) -> Result<()>59     pub fn wait(&self) -> Result<()> {
60         self.0.wait()
61     }
62 
63     /// Blocks until the event is signaled and clears the signal, or until the timeout duration
64     /// expires.
65     ///
66     /// It is undefined behavior to wait on an event from multiple threads or processes
67     /// simultaneously.
wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult>68     pub fn wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult> {
69         self.0.wait_timeout(timeout)
70     }
71 
72     /// Clears the event without blocking.
73     ///
74     /// If the event is not signaled, this has no effect and returns immediately.
reset(&self) -> Result<()>75     pub fn reset(&self) -> Result<()> {
76         self.0.reset()
77     }
78 
79     /// Clones the event. The event's state is shared between cloned instances.
80     ///
81     /// The documented caveats for `Event` also apply to a set of cloned instances, e.g., it is
82     /// undefined behavior to clone an event and then call `Event::wait` simultaneously on both
83     /// objects.
84     ///
85     /// Implementation notes:
86     ///   * Linux: The cloned instance uses a separate file descriptor.
87     ///   * Windows: The cloned instance uses a separate handle.
try_clone(&self) -> Result<Event>88     pub fn try_clone(&self) -> Result<Event> {
89         self.0.try_clone().map(Event)
90     }
91 }
92 
93 impl AsRawDescriptor for Event {
as_raw_descriptor(&self) -> RawDescriptor94     fn as_raw_descriptor(&self) -> RawDescriptor {
95         self.0.as_raw_descriptor()
96     }
97 }
98 
99 impl FromRawDescriptor for Event {
from_raw_descriptor(descriptor: RawDescriptor) -> Self100     unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
101         Event(PlatformEvent::from_raw_descriptor(descriptor))
102     }
103 }
104 
105 impl IntoRawDescriptor for Event {
into_raw_descriptor(self) -> RawDescriptor106     fn into_raw_descriptor(self) -> RawDescriptor {
107         self.0.into_raw_descriptor()
108     }
109 }
110 
111 impl From<Event> for SafeDescriptor {
from(evt: Event) -> Self112     fn from(evt: Event) -> Self {
113         Self::from(evt.0)
114     }
115 }
116 
117 impl From<SafeDescriptor> for Event {
from(sd: SafeDescriptor) -> Self118     fn from(sd: SafeDescriptor) -> Self {
119         Event(PlatformEvent::from(sd))
120     }
121 }
122