DrMemory: Fix a typo in the End2EndTest name.
[chromium-blink-merge.git] / cc / test / ordered_simple_task_runner.cc
blob3e0864c32a7c8fa78de1991ea8232bd7cb98ec7f
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/test/ordered_simple_task_runner.h"
7 #include <limits>
8 #include <set>
9 #include <sstream>
10 #include <string>
11 #include <vector>
13 #include "base/auto_reset.h"
14 #include "base/numerics/safe_conversions.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/trace_event/trace_event.h"
17 #include "base/trace_event/trace_event_argument.h"
19 #define TRACE_TASK(function, task) \
20 TRACE_EVENT_INSTANT1( \
21 "cc", function, TRACE_EVENT_SCOPE_THREAD, "task", task.AsValue());
23 #define TRACE_TASK_RUN(function, tag, task)
25 namespace cc {
27 // TestOrderablePendingTask implementation
28 TestOrderablePendingTask::TestOrderablePendingTask()
29 : base::TestPendingTask(),
30 task_id_(TestOrderablePendingTask::task_id_counter++) {
33 TestOrderablePendingTask::TestOrderablePendingTask(
34 const tracked_objects::Location& location,
35 const base::Closure& task,
36 base::TimeTicks post_time,
37 base::TimeDelta delay,
38 TestNestability nestability)
39 : base::TestPendingTask(location, task, post_time, delay, nestability),
40 task_id_(TestOrderablePendingTask::task_id_counter++) {
43 size_t TestOrderablePendingTask::task_id_counter = 0;
45 TestOrderablePendingTask::~TestOrderablePendingTask() {
48 bool TestOrderablePendingTask::operator==(
49 const TestOrderablePendingTask& other) const {
50 return task_id_ == other.task_id_;
53 bool TestOrderablePendingTask::operator<(
54 const TestOrderablePendingTask& other) const {
55 if (*this == other)
56 return false;
58 if (GetTimeToRun() == other.GetTimeToRun()) {
59 return task_id_ < other.task_id_;
61 return ShouldRunBefore(other);
64 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
65 TestOrderablePendingTask::AsValue() const {
66 scoped_refptr<base::trace_event::TracedValue> state =
67 new base::trace_event::TracedValue();
68 AsValueInto(state.get());
69 return state;
72 void TestOrderablePendingTask::AsValueInto(
73 base::trace_event::TracedValue* state) const {
74 state->SetInteger("id", base::saturated_cast<int>(task_id_));
75 state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
76 state->SetString("posted_from", location.ToString());
79 OrderedSimpleTaskRunner::OrderedSimpleTaskRunner(
80 base::SimpleTestTickClock* now_src,
81 bool advance_now)
82 : advance_now_(advance_now),
83 now_src_(now_src),
84 max_tasks_(kAbsoluteMaxTasks),
85 inside_run_tasks_until_(false) {
88 OrderedSimpleTaskRunner::~OrderedSimpleTaskRunner() {}
90 // static
91 base::TimeTicks OrderedSimpleTaskRunner::AbsoluteMaxNow() {
92 return base::TimeTicks::FromInternalValue(
93 std::numeric_limits<int64_t>::max());
96 // base::TestSimpleTaskRunner implementation
97 bool OrderedSimpleTaskRunner::PostDelayedTask(
98 const tracked_objects::Location& from_here,
99 const base::Closure& task,
100 base::TimeDelta delay) {
101 DCHECK(thread_checker_.CalledOnValidThread());
102 TestOrderablePendingTask pt(from_here, task, now_src_->NowTicks(), delay,
103 base::TestPendingTask::NESTABLE);
105 TRACE_TASK("OrderedSimpleTaskRunner::PostDelayedTask", pt);
106 pending_tasks_.insert(pt);
107 return true;
110 bool OrderedSimpleTaskRunner::PostNonNestableDelayedTask(
111 const tracked_objects::Location& from_here,
112 const base::Closure& task,
113 base::TimeDelta delay) {
114 DCHECK(thread_checker_.CalledOnValidThread());
115 TestOrderablePendingTask pt(from_here, task, now_src_->NowTicks(), delay,
116 base::TestPendingTask::NON_NESTABLE);
118 TRACE_TASK("OrderedSimpleTaskRunner::PostNonNestableDelayedTask", pt);
119 pending_tasks_.insert(pt);
120 return true;
123 bool OrderedSimpleTaskRunner::RunsTasksOnCurrentThread() const {
124 DCHECK(thread_checker_.CalledOnValidThread());
125 return true;
128 size_t OrderedSimpleTaskRunner::NumPendingTasks() const {
129 return pending_tasks_.size();
132 bool OrderedSimpleTaskRunner::HasPendingTasks() const {
133 return pending_tasks_.size() > 0;
136 base::TimeTicks OrderedSimpleTaskRunner::NextTaskTime() {
137 if (pending_tasks_.size() <= 0) {
138 return AbsoluteMaxNow();
141 return pending_tasks_.begin()->GetTimeToRun();
144 base::TimeDelta OrderedSimpleTaskRunner::DelayToNextTaskTime() {
145 DCHECK(thread_checker_.CalledOnValidThread());
147 if (pending_tasks_.size() <= 0) {
148 return AbsoluteMaxNow() - base::TimeTicks();
151 base::TimeDelta delay = NextTaskTime() - now_src_->NowTicks();
152 if (delay > base::TimeDelta())
153 return delay;
154 return base::TimeDelta();
157 const size_t OrderedSimpleTaskRunner::kAbsoluteMaxTasks =
158 std::numeric_limits<size_t>::max();
160 bool OrderedSimpleTaskRunner::RunTasksWhile(
161 base::Callback<bool(void)> condition) {
162 std::vector<base::Callback<bool(void)>> conditions(1);
163 conditions[0] = condition;
164 return RunTasksWhile(conditions);
167 bool OrderedSimpleTaskRunner::RunTasksWhile(
168 const std::vector<base::Callback<bool(void)>>& conditions) {
169 TRACE_EVENT2("cc",
170 "OrderedSimpleTaskRunner::RunPendingTasks",
171 "this",
172 AsValue(),
173 "nested",
174 inside_run_tasks_until_);
175 DCHECK(thread_checker_.CalledOnValidThread());
177 if (inside_run_tasks_until_)
178 return true;
180 base::AutoReset<bool> reset_inside_run_tasks_until_(&inside_run_tasks_until_,
181 true);
183 // Make a copy so we can append some extra run checks.
184 std::vector<base::Callback<bool(void)>> modifiable_conditions(conditions);
186 // Provide a timeout base on number of tasks run so this doesn't loop
187 // forever.
188 modifiable_conditions.push_back(TaskRunCountBelow(max_tasks_));
190 // If to advance now or not
191 if (!advance_now_) {
192 modifiable_conditions.push_back(NowBefore(now_src_->NowTicks()));
193 } else {
194 modifiable_conditions.push_back(AdvanceNow());
197 while (pending_tasks_.size() > 0) {
198 // Check if we should continue to run pending tasks.
199 bool condition_success = true;
200 for (std::vector<base::Callback<bool(void)>>::iterator it =
201 modifiable_conditions.begin();
202 it != modifiable_conditions.end();
203 it++) {
204 condition_success = it->Run();
205 if (!condition_success)
206 break;
209 // Conditions could modify the pending task length, so we need to recheck
210 // that there are tasks to run.
211 if (!condition_success || !HasPendingTasks()) {
212 break;
215 std::set<TestOrderablePendingTask>::iterator task_to_run =
216 pending_tasks_.begin();
218 TRACE_EVENT1("cc",
219 "OrderedSimpleTaskRunner::RunPendingTasks running",
220 "task",
221 task_to_run->AsValue());
222 task_to_run->task.Run();
225 pending_tasks_.erase(task_to_run);
228 return HasPendingTasks();
231 bool OrderedSimpleTaskRunner::RunPendingTasks() {
232 return RunTasksWhile(TaskExistedInitially());
235 bool OrderedSimpleTaskRunner::RunUntilIdle() {
236 return RunTasksWhile(std::vector<base::Callback<bool(void)>>());
239 bool OrderedSimpleTaskRunner::RunUntilTime(base::TimeTicks time) {
240 // If we are not auto advancing, force now forward to the time.
241 if (!advance_now_ && now_src_->NowTicks() < time)
242 now_src_->Advance(time - now_src_->NowTicks());
244 // Run tasks
245 bool result = RunTasksWhile(NowBefore(time));
247 // If the next task is after the stopping time and auto-advancing now, then
248 // force time to be the stopping time.
249 if (!result && advance_now_ && now_src_->NowTicks() < time) {
250 now_src_->Advance(time - now_src_->NowTicks());
253 return result;
256 bool OrderedSimpleTaskRunner::RunForPeriod(base::TimeDelta period) {
257 return RunUntilTime(now_src_->NowTicks() + period);
260 // base::trace_event tracing functionality
261 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
262 OrderedSimpleTaskRunner::AsValue() const {
263 scoped_refptr<base::trace_event::TracedValue> state =
264 new base::trace_event::TracedValue();
265 AsValueInto(state.get());
266 return state;
269 void OrderedSimpleTaskRunner::AsValueInto(
270 base::trace_event::TracedValue* state) const {
271 state->SetInteger("pending_tasks",
272 base::saturated_cast<int>(pending_tasks_.size()));
274 state->BeginArray("tasks");
275 for (std::set<TestOrderablePendingTask>::const_iterator it =
276 pending_tasks_.begin();
277 it != pending_tasks_.end();
278 ++it) {
279 state->BeginDictionary();
280 it->AsValueInto(state);
281 state->EndDictionary();
283 state->EndArray();
285 state->BeginDictionary("now_src");
286 state->SetDouble("now_in_ms", (now_src_->NowTicks() - base::TimeTicks())
287 .InMillisecondsF());
288 state->EndDictionary();
290 state->SetBoolean("advance_now", advance_now_);
291 state->SetBoolean("inside_run_tasks_until", inside_run_tasks_until_);
292 state->SetString("max_tasks", base::SizeTToString(max_tasks_));
295 base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskRunCountBelow(
296 size_t max_tasks) {
297 return base::Bind(&OrderedSimpleTaskRunner::TaskRunCountBelowCallback,
298 max_tasks,
299 base::Owned(new size_t(0)));
302 bool OrderedSimpleTaskRunner::TaskRunCountBelowCallback(size_t max_tasks,
303 size_t* tasks_run) {
304 return (*tasks_run)++ < max_tasks;
307 base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskExistedInitially() {
308 // base::Bind takes a copy of pending_tasks_
309 return base::Bind(&OrderedSimpleTaskRunner::TaskExistedInitiallyCallback,
310 base::Unretained(this),
311 pending_tasks_);
314 bool OrderedSimpleTaskRunner::TaskExistedInitiallyCallback(
315 const std::set<TestOrderablePendingTask>& existing_tasks) {
316 return existing_tasks.find(*pending_tasks_.begin()) != existing_tasks.end();
319 base::Callback<bool(void)> OrderedSimpleTaskRunner::NowBefore(
320 base::TimeTicks stop_at) {
321 return base::Bind(&OrderedSimpleTaskRunner::NowBeforeCallback,
322 base::Unretained(this),
323 stop_at);
325 bool OrderedSimpleTaskRunner::NowBeforeCallback(base::TimeTicks stop_at) {
326 return NextTaskTime() <= stop_at;
329 base::Callback<bool(void)> OrderedSimpleTaskRunner::AdvanceNow() {
330 return base::Bind(&OrderedSimpleTaskRunner::AdvanceNowCallback,
331 base::Unretained(this));
334 bool OrderedSimpleTaskRunner::AdvanceNowCallback() {
335 base::TimeTicks next_task_time = NextTaskTime();
336 if (now_src_->NowTicks() < next_task_time) {
337 now_src_->Advance(next_task_time - now_src_->NowTicks());
339 return true;
342 } // namespace cc