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