base/event.rs
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
5use std::time::Duration;
6
7use serde::Deserialize;
8use serde::Serialize;
9
10use crate::descriptor::AsRawDescriptor;
11use crate::descriptor::FromRawDescriptor;
12use crate::descriptor::IntoRawDescriptor;
13use crate::descriptor::SafeDescriptor;
14use crate::platform::PlatformEvent;
15use crate::RawDescriptor;
16use 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)]
34pub struct Event(pub(crate) PlatformEvent);
35
36#[derive(PartialEq, Eq, Debug)]
37pub enum EventWaitResult {
38 /// The `Event` was signaled.
39 Signaled,
40 /// Timeout limit reached.
41 TimedOut,
42}
43
44impl Event {
45 /// Creates new event in an unsignaled state.
46 pub fn new() -> Result<Event> {
47 PlatformEvent::new().map(Event)
48 }
49
50 /// Signals the event.
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.
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.
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.
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.
88 pub fn try_clone(&self) -> Result<Event> {
89 self.0.try_clone().map(Event)
90 }
91}
92
93impl AsRawDescriptor for Event {
94 fn as_raw_descriptor(&self) -> RawDescriptor {
95 self.0.as_raw_descriptor()
96 }
97}
98
99impl FromRawDescriptor for Event {
100 unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
101 Event(PlatformEvent::from_raw_descriptor(descriptor))
102 }
103}
104
105impl IntoRawDescriptor for Event {
106 fn into_raw_descriptor(self) -> RawDescriptor {
107 self.0.into_raw_descriptor()
108 }
109}
110
111impl From<Event> for SafeDescriptor {
112 fn from(evt: Event) -> Self {
113 Self::from(evt.0)
114 }
115}
116
117impl From<SafeDescriptor> for Event {
118 fn from(sd: SafeDescriptor) -> Self {
119 Event(PlatformEvent::from(sd))
120 }
121}