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}