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