blob: 32b6927043885aa9f599672ce4a96c18edea4924 [file] [log] [blame]
// Copyright 2017 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.
#ifndef LIB_APP_DRIVER_CPP_APP_DRIVER_H_
#define LIB_APP_DRIVER_CPP_APP_DRIVER_H_
#include <functional>
#include <memory>
#include <utility>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/memory/weak_ptr.h>
#include <lib/lifecycle/cpp/lifecycle_impl.h>
namespace modular {
// AppDriver is a wrapper that simplifies participating in lifecycle management
// by the application's parent. It does this by exposing the
// fuchsia::modular::Lifecycle service in
// component::StartupContext::outgoing().deprecated_services() and proxies
// the Terminate() call of fuchsia::modular::Lifecycle to the Terminate() method
// on your application's class instance.
//
// Usage:
//
// NOTE: Your application's class must implement:
//
// // Called by AppDriver. Call |done| once shutdown sequence is complete
// // and |this| will be scheduled for deletion on the current MessageLoop.
// void Terminate(const std::function<void()>& done);
//
// Example:
//
// class HelloWorldApp {
// public:
// HelloWorldApp(component::StartupContext* context) {
// context->outgoing().AddPublicService<..>(...);
// }
//
// void Terminate(const std::function<void()>& done) {
// done();
// }
// };
//
// int main(int argc, const char** argv) {
// async::Loop loop(&kAsyncLoopConfigAttachToThread);
// auto context = component::StartupContext::CreateFromStartupInfo();
// modular::AppDriver<HelloWorldApp> driver(
// context->outgoing().deprecated_services(),
// std::make_unique<HelloWorldApp>(context.get()),
// [&loop] { loop.Quit(); });
// loop.Run();
// return 0;
// }
template <typename Impl>
class AppDriver : LifecycleImpl::Delegate {
public:
AppDriver(component::ServiceNamespace* const outgoing_services,
std::unique_ptr<Impl> impl, std::function<void()> on_terminated)
: lifecycle_impl_(outgoing_services, this),
impl_(std::move(impl)),
on_terminated_(std::move(on_terminated)) {}
private:
// |LifecycleImpl::Delegate|
void Terminate() override {
impl_->Terminate([this] {
// Since this callback is called by |impl_|, we delay destroying it
// until the current stack rolls back up to the MessageLoop which
// guarantees impl_::Terminate() and anything that asynchronously
// invokes this callback are done running.
async::PostTask(async_get_default_dispatcher(), [this] {
impl_.reset();
on_terminated_();
});
});
}
LifecycleImpl lifecycle_impl_;
std::unique_ptr<Impl> impl_;
std::function<void()> on_terminated_;
FXL_DISALLOW_COPY_AND_ASSIGN(AppDriver);
};
} // namespace modular
#endif // LIB_APP_DRIVER_CPP_APP_DRIVER_H_