Skip to main content

starnix_lifecycle/
drop_notifier.rs

1// Copyright 2023 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
5use fuchsia_async as fasync;
6
7/// DropNotifier allows a client to be notified when is is dropped.
8///
9/// An object that has client that needs to be notified when it is dropped can keep a
10/// `DropNotifier` in its member. Client can then request a waiter from it. When the `DropNotifier`
11/// is dropped, the `waiter` will be signaled with a PEER_CLOSED event.
12#[derive(Debug)]
13pub struct DropNotifier {
14    _local_event: zx::EventPair,
15    notified_event: zx::EventPair,
16}
17
18/// A waiter on a `DropNotifier`.
19pub type DropWaiter = fasync::RWHandle<zx::EventPair>;
20
21impl DropNotifier {
22    /// Get a new waiter on this notifier. It will be notified when this object is dropped.
23    pub fn waiter(&self) -> DropWaiter {
24        fasync::RWHandle::new(self.event())
25    }
26
27    /// Get an event pair that will receive a PEER_CLOSED signal when this object is dropped.
28    pub fn event(&self) -> zx::EventPair {
29        self.notified_event.duplicate_handle(zx::Rights::SAME_RIGHTS).expect("duplicate event")
30    }
31}
32
33impl Default for DropNotifier {
34    fn default() -> Self {
35        let (_local_event, notified_event) = zx::EventPair::create();
36        Self { _local_event, notified_event }
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43    use std::pin::pin;
44
45    #[fuchsia::test]
46    async fn check_notifier() {
47        let notifier = DropNotifier::default();
48        let waiter = notifier.waiter();
49        let mut on_closed = pin!(waiter.on_closed());
50        assert!(futures::poll!(&mut on_closed).is_pending());
51        assert!(!waiter.is_closed());
52        std::mem::drop(notifier);
53        let on_closed2 = waiter.on_closed();
54        assert!(waiter.is_closed());
55        assert_eq!(on_closed.await.expect("await"), zx::Signals::EVENTPAIR_PEER_CLOSED);
56        assert_eq!(on_closed2.await.expect("await"), zx::Signals::EVENTPAIR_PEER_CLOSED);
57    }
58}