1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Type-safe bindings for Zircon event pairs.
6 
7 use {AsHandleRef, Cookied, HandleBased, Handle, HandleRef, Peered, Status};
8 use {sys, ok};
9 
10 /// An object representing a Zircon
11 /// [event pair](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Other-IPC_Events_Event-Pairs_and-User-Signals).
12 ///
13 /// As essentially a subtype of `Handle`, it can be freely interconverted.
14 #[derive(Debug, Eq, PartialEq)]
15 pub struct EventPair(Handle);
16 impl_handle_based!(EventPair);
17 impl Peered for EventPair {}
18 impl Cookied for EventPair {}
19 
20 impl EventPair {
21     /// Create an event pair, a pair of objects which can signal each other. Wraps the
22     /// [zx_eventpair_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/eventpair_create.md)
23     /// syscall.
create() -> Result<(EventPair, EventPair), Status>24     pub fn create() -> Result<(EventPair, EventPair), Status> {
25         let mut out0 = 0;
26         let mut out1 = 0;
27         let options = 0;
28         let status = unsafe { sys::zx_eventpair_create(options, &mut out0, &mut out1) };
29         ok(status)?;
30         unsafe {
31             Ok((
32                 Self::from(Handle::from_raw(out0)),
33                 Self::from(Handle::from_raw(out1))
34             ))
35         }
36     }
37 }
38 
39 #[cfg(test)]
40 mod tests {
41     use super::*;
42     use {DurationNum, Signals};
43 
44     #[test]
wait_and_signal_peer()45     fn wait_and_signal_peer() {
46         let (p1, p2) = EventPair::create().unwrap();
47         let eighty_ms = 80.millis();
48 
49         // Waiting on one without setting any signal should time out.
50         assert_eq!(p2.wait_handle(Signals::USER_0, eighty_ms.after_now()), Err(Status::TIMED_OUT));
51 
52         // If we set a signal, we should be able to wait for it.
53         assert!(p1.signal_peer(Signals::NONE, Signals::USER_0).is_ok());
54         assert_eq!(p2.wait_handle(Signals::USER_0, eighty_ms.after_now()).unwrap(),
55             Signals::USER_0);
56 
57         // Should still work, signals aren't automatically cleared.
58         assert_eq!(p2.wait_handle(Signals::USER_0, eighty_ms.after_now()).unwrap(),
59             Signals::USER_0);
60 
61         // Now clear it, and waiting should time out again.
62         assert!(p1.signal_peer(Signals::USER_0, Signals::NONE).is_ok());
63         assert_eq!(p2.wait_handle(Signals::USER_0, eighty_ms.after_now()), Err(Status::TIMED_OUT));
64     }
65 }
66