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