blob: d8a6225e47b666450dafd2dd805ee19331457b6b [file] [log] [blame]
// Copyright 2018 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 "peridot/lib/util/wait_until_idle.h"
namespace util {
IdleWaiter::Activity::Activity(fxl::WeakPtr<IdleWaiter> tracker)
: tracker_(tracker) {
tracker_->activity_ = this;
}
IdleWaiter::Activity::~Activity() {
if (tracker_) {
tracker_->activity_ = nullptr;
tracker_->PostIdleCheck();
}
}
IdleWaiter::IdleWaiter()
: message_loop_(fsl::MessageLoop::GetCurrent()), weak_ptr_factory_(this) {}
IdleWaiter::~IdleWaiter() = default;
IdleWaiter::ActivityToken IdleWaiter::RegisterOngoingActivity() {
FXL_DCHECK(message_loop_ == fsl::MessageLoop::GetCurrent());
if (activity_) {
return ActivityToken(activity_);
} else {
// |activity_| is set in the |Activity| constructor and cleared in
// the destructor
return fxl::MakeRefCounted<Activity>(weak_ptr_factory_.GetWeakPtr());
}
}
void IdleWaiter::WaitUntilIdle(fxl::Closure callback) {
callbacks_.push_back(std::move(callback));
PostIdleCheck();
}
void IdleWaiter::PostIdleCheck() {
if (!(callbacks_.empty() || activity_ || idle_check_pending_)) {
FXL_DCHECK(message_loop_ == fsl::MessageLoop::GetCurrent());
message_loop_->PostQuitTask();
idle_check_pending_ = true;
}
}
bool IdleWaiter::FinishIdleCheck() {
if (idle_check_pending_) {
message_loop_->RunUntilIdle();
if (!activity_) {
for (const auto& callback : callbacks_) {
callback();
}
callbacks_.clear();
}
// Otherwise, |PostIdleCheck| will be invoked again when |activity_| is
// released.
idle_check_pending_ = false;
return true;
} else {
return false;
}
}
} // namespace util