blob: d80586194d472f5c695750cb84ba665abfd2600e [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.
#include "task.h"
namespace devmgr {
Task::Task(async_dispatcher_t* dispatcher, Completion completion)
: completion_(std::move(completion)), dispatcher_(dispatcher) {
ZX_ASSERT(async_task_.Post(dispatcher_) == ZX_OK);
}
Task::~Task() {
ZX_ASSERT(dependents_.is_empty());
}
void Task::ExecuteTask(async_dispatcher_t* dispatcher, async::TaskBase* task, zx_status_t status) {
// If we've already completed, we have no more work to do.
// If we have outstanding dependencies, we'll be rescheduled when they're done
if (std::holds_alternative<zx_status_t>(status_) ||
finished_dependencies_count_ != total_dependencies_count_) {
return;
}
Run();
}
// Called to record a new dependency
void Task::AddDependency(const fbl::RefPtr<Task>& dependency) {
dependency->self_ = dependency;
dependency->RegisterDependent(fbl::WrapRefPtr(this));
}
void Task::RegisterDependent(fbl::RefPtr<Task> dependent) {
++dependent->total_dependencies_count_;
// Check if we're already completed
auto* status = std::get_if<zx_status_t>(&status_);
if (status != nullptr) {
return dependent->DependencyComplete(*status);
}
dependents_.push_back(std::move(dependent));
}
void Task::DependencyComplete(zx_status_t status) {
++finished_dependencies_count_;
if (finished_dependencies_count_ == total_dependencies_count_) {
ZX_ASSERT(async_task_.Post(dispatcher_) == ZX_OK);
}
if (status != ZX_OK && std::holds_alternative<Incomplete>(status_)) {
DependencyFailed(status);
}
}
void Task::Complete(zx_status_t status) {
ZX_ASSERT(std::holds_alternative<Incomplete>(status_));
status_ = status;
for (auto& dependent : dependents_) {
dependent->DependencyComplete(status);
}
dependents_.reset();
Completion completion(std::move(completion_));
if (completion) {
completion(status);
}
self_.reset();
}
} // namespace devmgr