Setup a experiment to enable background tracing.
[chromium-blink-merge.git] / cc / test / ordered_simple_task_runner.cc
blob4bf97837371973ccbb2821c922e4ea4add8cf18d
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/strings/string_number_conversions.h"
15 #include "base/trace_event/trace_event.h"
16 #include "base/trace_event/trace_event_argument.h"
18 #define TRACE_TASK(function, task) \
19 TRACE_EVENT_INSTANT1( \
20 "cc", function, TRACE_EVENT_SCOPE_THREAD, "task", task.AsValue());
22 #define TRACE_TASK_RUN(function, tag, task)
24 namespace cc {
26 // TestOrderablePendingTask implementation
27 TestOrderablePendingTask::TestOrderablePendingTask()
28 : base::TestPendingTask(),
29 task_id_(TestOrderablePendingTask::task_id_counter++) {
32 TestOrderablePendingTask::TestOrderablePendingTask(
33 const tracked_objects::Location& location,
34 const base::Closure& task,
35 base::TimeTicks post_time,
36 base::TimeDelta delay,
37 TestNestability nestability)
38 : base::TestPendingTask(location, task, post_time, delay, nestability),
39 task_id_(TestOrderablePendingTask::task_id_counter++) {
42 size_t TestOrderablePendingTask::task_id_counter = 0;
44 TestOrderablePendingTask::~TestOrderablePendingTask() {
47 bool TestOrderablePendingTask::operator==(
48 const TestOrderablePendingTask& other) const {
49 return task_id_ == other.task_id_;
52 bool TestOrderablePendingTask::operator<(
53 const TestOrderablePendingTask& other) const {
54 if (*this == other)
55 return false;
57 if (GetTimeToRun() == other.GetTimeToRun()) {
58 return task_id_ < other.task_id_;
60 return ShouldRunBefore(other);
63 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
64 TestOrderablePendingTask::AsValue() const {
65 scoped_refptr<base::trace_event::TracedValue> state =
66 new base::trace_event::TracedValue();
67 AsValueInto(state.get());
68 return state;
71 void TestOrderablePendingTask::AsValueInto(
72 base::trace_event::TracedValue* state) const {
73 state->SetInteger("id", task_id_);
74 state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
75 state->SetString("posted_from", location.ToString());
78 OrderedSimpleTaskRunner::OrderedSimpleTaskRunner()
79 : advance_now_(true),
80 now_src_(TestNowSource::Create(0)),
81 max_tasks_(kAbsoluteMaxTasks),
82 inside_run_tasks_until_(false) {
85 OrderedSimpleTaskRunner::OrderedSimpleTaskRunner(
86 scoped_refptr<TestNowSource> now_src,
87 bool advance_now)
88 : advance_now_(advance_now),
89 now_src_(now_src),
90 max_tasks_(kAbsoluteMaxTasks),
91 inside_run_tasks_until_(false) {
94 OrderedSimpleTaskRunner::~OrderedSimpleTaskRunner() {}
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(
103 from_here, task, now_src_->Now(), delay, 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,
116 task,
117 now_src_->Now(),
118 delay,
119 base::TestPendingTask::NON_NESTABLE);
121 TRACE_TASK("OrderedSimpleTaskRunner::PostNonNestableDelayedTask", pt);
122 pending_tasks_.insert(pt);
123 return true;
126 bool OrderedSimpleTaskRunner::RunsTasksOnCurrentThread() const {
127 DCHECK(thread_checker_.CalledOnValidThread());
128 return true;
131 size_t OrderedSimpleTaskRunner::NumPendingTasks() const {
132 return pending_tasks_.size();
135 bool OrderedSimpleTaskRunner::HasPendingTasks() const {
136 return pending_tasks_.size() > 0;
139 base::TimeTicks OrderedSimpleTaskRunner::NextTaskTime() {
140 if (pending_tasks_.size() <= 0) {
141 return TestNowSource::kAbsoluteMaxNow;
144 return pending_tasks_.begin()->GetTimeToRun();
147 base::TimeDelta OrderedSimpleTaskRunner::DelayToNextTaskTime() {
148 DCHECK(thread_checker_.CalledOnValidThread());
150 if (pending_tasks_.size() <= 0) {
151 return TestNowSource::kAbsoluteMaxNow - base::TimeTicks();
154 base::TimeDelta delay = NextTaskTime() - now_src_->Now();
155 if (delay > base::TimeDelta())
156 return delay;
157 return base::TimeDelta();
160 const size_t OrderedSimpleTaskRunner::kAbsoluteMaxTasks =
161 std::numeric_limits<size_t>::max();
163 bool OrderedSimpleTaskRunner::RunTasksWhile(
164 base::Callback<bool(void)> condition) {
165 std::vector<base::Callback<bool(void)>> conditions(1);
166 conditions[0] = condition;
167 return RunTasksWhile(conditions);
170 bool OrderedSimpleTaskRunner::RunTasksWhile(
171 const std::vector<base::Callback<bool(void)>>& conditions) {
172 TRACE_EVENT2("cc",
173 "OrderedSimpleTaskRunner::RunPendingTasks",
174 "this",
175 AsValue(),
176 "nested",
177 inside_run_tasks_until_);
178 DCHECK(thread_checker_.CalledOnValidThread());
180 if (inside_run_tasks_until_)
181 return true;
183 base::AutoReset<bool> reset_inside_run_tasks_until_(&inside_run_tasks_until_,
184 true);
186 // Make a copy so we can append some extra run checks.
187 std::vector<base::Callback<bool(void)>> modifiable_conditions(conditions);
189 // Provide a timeout base on number of tasks run so this doesn't loop
190 // forever.
191 modifiable_conditions.push_back(TaskRunCountBelow(max_tasks_));
193 // If to advance now or not
194 if (!advance_now_) {
195 modifiable_conditions.push_back(NowBefore(now_src_->Now()));
196 } else {
197 modifiable_conditions.push_back(AdvanceNow());
200 while (pending_tasks_.size() > 0) {
201 // Check if we should continue to run pending tasks.
202 bool condition_success = true;
203 for (std::vector<base::Callback<bool(void)>>::iterator it =
204 modifiable_conditions.begin();
205 it != modifiable_conditions.end();
206 it++) {
207 condition_success = it->Run();
208 if (!condition_success)
209 break;
212 // Conditions could modify the pending task length, so we need to recheck
213 // that there are tasks to run.
214 if (!condition_success || !HasPendingTasks()) {
215 break;
218 std::set<TestOrderablePendingTask>::iterator task_to_run =
219 pending_tasks_.begin();
221 TRACE_EVENT1("cc",
222 "OrderedSimpleTaskRunner::RunPendingTasks running",
223 "task",
224 task_to_run->AsValue());
225 task_to_run->task.Run();
228 pending_tasks_.erase(task_to_run);
231 return HasPendingTasks();
234 bool OrderedSimpleTaskRunner::RunPendingTasks() {
235 return RunTasksWhile(TaskExistedInitially());
238 bool OrderedSimpleTaskRunner::RunUntilIdle() {
239 return RunTasksWhile(std::vector<base::Callback<bool(void)>>());
242 bool OrderedSimpleTaskRunner::RunUntilTime(base::TimeTicks time) {
243 // If we are not auto advancing, force now forward to the time.
244 if (!advance_now_ && now_src_->Now() < time)
245 now_src_->SetNow(time);
247 // Run tasks
248 bool result = RunTasksWhile(NowBefore(time));
250 // If the next task is after the stopping time and auto-advancing now, then
251 // force time to be the stopping time.
252 if (!result && advance_now_ && now_src_->Now() < time) {
253 now_src_->SetNow(time);
256 return result;
259 bool OrderedSimpleTaskRunner::RunForPeriod(base::TimeDelta period) {
260 return RunUntilTime(now_src_->Now() + period);
263 // base::trace_event tracing functionality
264 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
265 OrderedSimpleTaskRunner::AsValue() const {
266 scoped_refptr<base::trace_event::TracedValue> state =
267 new base::trace_event::TracedValue();
268 AsValueInto(state.get());
269 return state;
272 void OrderedSimpleTaskRunner::AsValueInto(
273 base::trace_event::TracedValue* state) const {
274 state->SetInteger("pending_tasks", pending_tasks_.size());
276 state->BeginArray("tasks");
277 for (std::set<TestOrderablePendingTask>::const_iterator it =
278 pending_tasks_.begin();
279 it != pending_tasks_.end();
280 ++it) {
281 state->BeginDictionary();
282 it->AsValueInto(state);
283 state->EndDictionary();
285 state->EndArray();
287 state->BeginDictionary("now_src");
288 now_src_->AsValueInto(state);
289 state->EndDictionary();
291 state->SetBoolean("advance_now", advance_now_);
292 state->SetBoolean("inside_run_tasks_until", inside_run_tasks_until_);
293 state->SetString("max_tasks", base::SizeTToString(max_tasks_));
296 base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskRunCountBelow(
297 size_t max_tasks) {
298 return base::Bind(&OrderedSimpleTaskRunner::TaskRunCountBelowCallback,
299 max_tasks,
300 base::Owned(new size_t(0)));
303 bool OrderedSimpleTaskRunner::TaskRunCountBelowCallback(size_t max_tasks,
304 size_t* tasks_run) {
305 return (*tasks_run)++ < max_tasks;
308 base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskExistedInitially() {
309 // base::Bind takes a copy of pending_tasks_
310 return base::Bind(&OrderedSimpleTaskRunner::TaskExistedInitiallyCallback,
311 base::Unretained(this),
312 pending_tasks_);
315 bool OrderedSimpleTaskRunner::TaskExistedInitiallyCallback(
316 const std::set<TestOrderablePendingTask>& existing_tasks) {
317 return existing_tasks.find(*pending_tasks_.begin()) != existing_tasks.end();
320 base::Callback<bool(void)> OrderedSimpleTaskRunner::NowBefore(
321 base::TimeTicks stop_at) {
322 return base::Bind(&OrderedSimpleTaskRunner::NowBeforeCallback,
323 base::Unretained(this),
324 stop_at);
326 bool OrderedSimpleTaskRunner::NowBeforeCallback(base::TimeTicks stop_at) {
327 return NextTaskTime() <= stop_at;
330 base::Callback<bool(void)> OrderedSimpleTaskRunner::AdvanceNow() {
331 return base::Bind(&OrderedSimpleTaskRunner::AdvanceNowCallback,
332 base::Unretained(this));
335 bool OrderedSimpleTaskRunner::AdvanceNowCallback() {
336 base::TimeTicks next_task_time = NextTaskTime();
337 if (now_src_->Now() < next_task_time) {
338 now_src_->SetNow(next_task_time);
340 return true;
343 } // namespace cc