// Copyright 2020 The ChromiumOS Authors1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34use std::time::Duration;56use serde::Deserialize;7use serde::Serialize;89use crate::descriptor::AsRawDescriptor;10use crate::descriptor::FromRawDescriptor;11use crate::descriptor::IntoRawDescriptor;12use crate::descriptor::SafeDescriptor;13use crate::platform::PlatformEvent;14use crate::RawDescriptor;15use crate::Result;1617/// An inter-process event wait/notify mechanism. Loosely speaking: Writes signal the event. Reads18/// block until the event is signaled and then clear the signal.19///20/// Supports multiple simultaneous writers (i.e. signalers) but only one simultaneous reader (i.e.21/// waiter). The behavior of multiple readers is undefined in cross platform code.22///23/// Multiple `Event`s can be polled at once via `WaitContext`.24///25/// Implementation notes:26/// - Uses eventfd on Linux.27/// - Uses synchapi event objects on Windows.28/// - The `Event` and `WaitContext` APIs together cannot easily be implemented with the same29/// semantics on all platforms. In particular, it is difficult to support multiple readers, so30/// only a single reader is allowed for now. Multiple readers will result in undefined behavior.31#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]32#[serde(transparent)]33pub struct Event(pub(crate) PlatformEvent);3435#[derive(PartialEq, Eq, Debug)]36pub enum EventWaitResult {37/// The `Event` was signaled.38Signaled,39/// Timeout limit reached.40TimedOut,41}4243impl Event {44/// Creates new event in an unsignaled state.45pub fn new() -> Result<Event> {46PlatformEvent::new().map(Event)47}4849/// Signals the event.50pub fn signal(&self) -> Result<()> {51self.0.signal()52}5354/// Blocks until the event is signaled and clears the signal.55///56/// It is undefined behavior to wait on an event from multiple threads or processes57/// simultaneously.58pub fn wait(&self) -> Result<()> {59self.0.wait()60}6162/// Blocks until the event is signaled and clears the signal, or until the timeout duration63/// expires.64///65/// It is undefined behavior to wait on an event from multiple threads or processes66/// simultaneously.67pub fn wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult> {68self.0.wait_timeout(timeout)69}7071/// Clears the event without blocking.72///73/// If the event is not signaled, this has no effect and returns immediately.74pub fn reset(&self) -> Result<()> {75self.0.reset()76}7778/// Clones the event. The event's state is shared between cloned instances.79///80/// The documented caveats for `Event` also apply to a set of cloned instances, e.g., it is81/// undefined behavior to clone an event and then call `Event::wait` simultaneously on both82/// objects.83///84/// Implementation notes:85/// * Linux: The cloned instance uses a separate file descriptor.86/// * Windows: The cloned instance uses a separate handle.87pub fn try_clone(&self) -> Result<Event> {88self.0.try_clone().map(Event)89}90}9192impl AsRawDescriptor for Event {93fn as_raw_descriptor(&self) -> RawDescriptor {94self.0.as_raw_descriptor()95}96}9798impl FromRawDescriptor for Event {99unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {100Event(PlatformEvent::from_raw_descriptor(descriptor))101}102}103104impl IntoRawDescriptor for Event {105fn into_raw_descriptor(self) -> RawDescriptor {106self.0.into_raw_descriptor()107}108}109110impl From<Event> for SafeDescriptor {111fn from(evt: Event) -> Self {112Self::from(evt.0)113}114}115116impl From<SafeDescriptor> for Event {117fn from(sd: SafeDescriptor) -> Self {118Event(PlatformEvent::from(sd))119}120}121122123