blob: 0833971aa02408d926da90c6ec3445904ae6f9e8 [file] [log] [blame]
// Copyright 2019 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.
use {
crate::model::{
error::ModelError,
hooks::{Event, EventType, Hook, HooksRegistration},
},
async_trait::async_trait,
futures::{channel::*, lock::Mutex},
std::sync::{Arc, Weak},
};
/// Notifies when the root instance has been destroyed by ComponentManager.
/// This is used to terminate ComponentManager when the root component has been destroyed.
pub struct RootRealmStopNotifier {
rx: Mutex<Option<oneshot::Receiver<()>>>,
tx: Mutex<Option<oneshot::Sender<()>>>,
}
impl RootRealmStopNotifier {
pub fn new() -> Self {
let (tx, rx) = oneshot::channel();
Self { rx: Mutex::new(Some(rx)), tx: Mutex::new(Some(tx)) }
}
pub fn hooks(self: &Arc<Self>) -> Vec<HooksRegistration> {
vec![HooksRegistration::new(
"RootRealmStopNotifier",
vec![EventType::Stopped],
Arc::downgrade(self) as Weak<dyn Hook>,
)]
}
pub async fn wait_for_root_realm_stop(&self) {
let rx = self.rx.lock().await.take();
if let Some(rx) = rx {
rx.await.expect("Failed to wait for root instance to be stopped");
}
}
}
#[async_trait]
impl Hook for RootRealmStopNotifier {
async fn on(self: Arc<Self>, event: &Event) -> Result<(), ModelError> {
if event.target_moniker.is_root() {
let tx = self.tx.lock().await.take();
if let Some(tx) = tx {
tx.send(()).expect("Could not notify on Stopped of root realm");
}
}
Ok(())
}
}