blob: e0e0827baabfb049ac380eac362b39c31d873051 [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::{
component::{ComponentInstance, StartReason},
error::ModelError,
model::Model,
},
async_trait::async_trait,
moniker::AbsoluteMoniker,
std::sync::{Arc, Weak},
};
/// A trait to enable support for different `start()` implementations. This is used,
/// for example, for testing code that depends on `start()`, but no other `Model`
/// functionality.
#[async_trait]
pub trait Starter: Send + Sync {
async fn start_instance<'a>(
&'a self,
abs_moniker: &'a AbsoluteMoniker,
reason: &'a StartReason,
) -> Result<Arc<ComponentInstance>, ModelError>;
}
#[async_trait]
impl Starter for Arc<Model> {
/// Starts the component instance with the specified moniker. This has the following effects:
/// - Binds to the parent instance.
/// - Starts the component instance, if it is not already running and not shut down.
/// - Starts any descendant component instances that need to be eagerly started.
// TODO: This function starts the parent component, but doesn't track the bindings anywhere.
// This means that when the child stops and the parent has no other reason to run, we won't
// stop the parent. To solve this, we need to track the bindings.
async fn start_instance<'a>(
&'a self,
abs_moniker: &'a AbsoluteMoniker,
reason: &'a StartReason,
) -> Result<Arc<ComponentInstance>, ModelError> {
start_moniker(self, abs_moniker, reason).await
}
}
#[async_trait]
impl Starter for Weak<Model> {
async fn start_instance<'a>(
&'a self,
abs_moniker: &'a AbsoluteMoniker,
reason: &'a StartReason,
) -> Result<Arc<ComponentInstance>, ModelError> {
if let Some(model) = self.upgrade() {
model.start_instance(abs_moniker, reason).await
} else {
Err(ModelError::ModelNotAvailable)
}
}
}
/// Starts the component instance in the given component if it's not already running.
/// Returns the component that was bound to.
pub async fn start_moniker<'a>(
model: &'a Arc<Model>,
abs_moniker: &'a AbsoluteMoniker,
reason: &StartReason,
) -> Result<Arc<ComponentInstance>, ModelError> {
let component = model.look_up(abs_moniker).await?;
component.start(reason).await?;
Ok(component)
}