File: fake_task_runner.cc

package info (click to toggle)
android-platform-tools 34.0.5-12
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 150,900 kB
  • sloc: cpp: 805,786; java: 293,500; ansic: 128,288; xml: 127,491; python: 41,481; sh: 14,245; javascript: 9,665; cs: 3,846; asm: 2,049; makefile: 1,917; yacc: 440; awk: 368; ruby: 183; sql: 140; perl: 88; lex: 67
file content (76 lines) | stat: -rw-r--r-- 2,338 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// 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