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
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Type-safe bindings for Zircon event pairs.
use crate::{ok, AsHandleRef, Handle, HandleBased, HandleRef, Peered};
/// An object representing a Zircon
/// [event_pair](https://fuchsia.dev/fuchsia-src/concepts/kernel/concepts#events_event_pairs)
///
/// As essentially a subtype of `Handle`, it can be freely interconverted.
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct EventPair(Handle);
impl_handle_based!(EventPair);
impl Peered for EventPair {}
impl EventPair {
/// Create an event pair, a pair of objects which can signal each other. Wraps the
/// [zx_eventpair_create](https://fuchsia.dev/fuchsia-src/reference/syscalls/eventpair_create.md)
/// syscall.
///
/// # Panics
///
/// If the kernel reports no available memory to create an event pair or the process' job
/// policy disallows EventPair creation.
pub fn create() -> (Self, Self) {
let mut out0 = 0;
let mut out1 = 0;
let options = 0;
let status = unsafe { crate::sys::zx_eventpair_create(options, &mut out0, &mut out1) };
ok(status).expect(
"eventpair creation always succeeds except with OOM or when job policy denies it",
);
unsafe { (Self::from(Handle::from_raw(out0)), Self::from(Handle::from_raw(out1))) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Duration, MonotonicInstant, Signals, Status};
#[test]
fn wait_and_signal_peer() {
let (p1, p2) = EventPair::create();
let eighty_ms = Duration::from_millis(80);
// Waiting on one without setting any signal should time out.
assert_eq!(
p2.wait_handle(Signals::USER_0, MonotonicInstant::after(eighty_ms)),
Err(Status::TIMED_OUT)
);
// If we set a signal, we should be able to wait for it.
assert!(p1.signal_peer(Signals::NONE, Signals::USER_0).is_ok());
assert_eq!(
p2.wait_handle(Signals::USER_0, MonotonicInstant::after(eighty_ms)).unwrap(),
Signals::USER_0
);
// Should still work, signals aren't automatically cleared.
assert_eq!(
p2.wait_handle(Signals::USER_0, MonotonicInstant::after(eighty_ms)).unwrap(),
Signals::USER_0
);
// Now clear it, and waiting should time out again.
assert!(p1.signal_peer(Signals::USER_0, Signals::NONE).is_ok());
assert_eq!(
p2.wait_handle(Signals::USER_0, MonotonicInstant::after(eighty_ms)),
Err(Status::TIMED_OUT)
);
}
}