blob: 922edc8e23d3dbc01b36a8be372b7d1f4df555e9 [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 "src/ledger/bin/synchronization/completer.h"
#include "src/ledger/lib/callback/scoped_task_runner.h"
#include "src/ledger/lib/coroutine/coroutine.h"
#include "src/ledger/lib/logging/logging.h"
namespace ledger {
Completer::Completer(async_dispatcher_t* dispatcher) : task_runner_(dispatcher) {}
Completer::~Completer() = default;
void Completer::Complete(Status status) {
LEDGER_DCHECK(!completed_);
completed_ = true;
status_ = status;
// We need to move the callbacks in the stack since calling any of the
// them might lead to the deletion of this object, invalidating callbacks_.
std::vector<fit::function<void(Status)>> callbacks = std::move(callbacks_);
callbacks_.clear();
task_runner_.PostTask([status, callbacks = std::move(callbacks)] {
for (const auto& callback : callbacks) {
callback(status);
}
});
}
void Completer::WaitUntilDone(fit::function<void(Status)> callback) {
if (completed_) {
callback(status_);
}
callbacks_.push_back(std::move(callback));
}
bool Completer::IsCompleted() { return completed_; }
Status SyncWaitUntilDone(coroutine::CoroutineHandler* handler, Completer* completer) {
Status status;
if (coroutine::SyncCall(
handler,
[completer](fit::function<void(Status)> callback) {
completer->WaitUntilDone(std::move(callback));
},
&status) == coroutine::ContinuationStatus::INTERRUPTED) {
return Status::INTERRUPTED;
}
return status;
}
} // namespace ledger