77 lines
2.3 KiB
C++
77 lines
2.3 KiB
C++
// Copyright 2019 The Chromium 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 "platform/test/fake_task_runner.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "util/osp_logging.h"
|
|
|
|
namespace openscreen {
|
|
|
|
FakeTaskRunner::FakeTaskRunner(FakeClock* clock) : clock_(clock) {
|
|
OSP_CHECK(clock_);
|
|
clock_->SubscribeToTimeChanges(this);
|
|
}
|
|
|
|
FakeTaskRunner::~FakeTaskRunner() {
|
|
clock_->UnsubscribeFromTimeChanges(this);
|
|
}
|
|
|
|
void FakeTaskRunner::RunTasksUntilIdle() {
|
|
// If there is bad code that posts tasks indefinitely, this loop will never
|
|
// break. However, that also means there is a code path spinning a CPU core at
|
|
// 100% all the time. Rather than mitigate this problem scenario, purposely
|
|
// let it manifest here in the hopes that unit testing will reveal it (e.g., a
|
|
// unit test that never finishes running).
|
|
for (;;) {
|
|
const auto current_time = FakeClock::now();
|
|
const auto end_of_range = delayed_tasks_.upper_bound(current_time);
|
|
for (auto it = delayed_tasks_.begin(); it != end_of_range; ++it) {
|
|
ready_to_run_tasks_.push_back(std::move(it->second));
|
|
}
|
|
delayed_tasks_.erase(delayed_tasks_.begin(), end_of_range);
|
|
|
|
if (ready_to_run_tasks_.empty()) {
|
|
break;
|
|
}
|
|
|
|
std::vector<Task> running_tasks;
|
|
running_tasks.swap(ready_to_run_tasks_);
|
|
for (Task& running_task : running_tasks) {
|
|
// Move the task out of the vector and onto the stack so that it destroys
|
|
// just after being run. This helps catch "dangling reference/pointer"
|
|
// bugs.
|
|
Task task = std::move(running_task);
|
|
task();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FakeTaskRunner::PostPackagedTask(Task task) {
|
|
ready_to_run_tasks_.push_back(std::move(task));
|
|
}
|
|
|
|
void FakeTaskRunner::PostPackagedTaskWithDelay(Task task,
|
|
Clock::duration delay) {
|
|
delayed_tasks_.emplace(
|
|
std::make_pair(FakeClock::now() + delay, std::move(task)));
|
|
}
|
|
|
|
bool FakeTaskRunner::IsRunningOnTaskRunner() {
|
|
return true;
|
|
}
|
|
|
|
Clock::time_point FakeTaskRunner::GetResumeTime() const {
|
|
if (!ready_to_run_tasks_.empty()) {
|
|
return FakeClock::now();
|
|
}
|
|
if (!delayed_tasks_.empty()) {
|
|
return delayed_tasks_.begin()->first;
|
|
}
|
|
return Clock::time_point::max();
|
|
}
|
|
|
|
} // namespace openscreen
|