blob: 4b3a80a2f1a3a387993d3a452e43fed79d3f9791 [file] [log] [blame]
[email protected]3d3b37e92014-05-29 02:31:231// 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.
4
5#include "cc/test/ordered_simple_task_runner.h"
6
avi02a4d172015-12-21 06:14:367#include <stddef.h>
8#include <stdint.h>
9
mithro0c0ac6a2014-09-10 01:03:3610#include <limits>
11#include <set>
12#include <sstream>
13#include <string>
tzik070c8ffb2017-03-29 05:28:1214#include <utility>
mithro0c0ac6a2014-09-10 01:03:3615#include <vector>
[email protected]3d3b37e92014-05-29 02:31:2316
mithro0c0ac6a2014-09-10 01:03:3617#include "base/auto_reset.h"
vmpstr45816062015-06-10 23:00:0018#include "base/numerics/safe_conversions.h"
mithro0c0ac6a2014-09-10 01:03:3619#include "base/strings/string_number_conversions.h"
primianoc06e2382015-01-28 04:21:4920#include "base/trace_event/trace_event.h"
21#include "base/trace_event/trace_event_argument.h"
[email protected]3d3b37e92014-05-29 02:31:2322
mithro0c0ac6a2014-09-10 01:03:3623#define TRACE_TASK(function, task) \
24 TRACE_EVENT_INSTANT1( \
25 "cc", function, TRACE_EVENT_SCOPE_THREAD, "task", task.AsValue());
[email protected]3d3b37e92014-05-29 02:31:2326
mithro0c0ac6a2014-09-10 01:03:3627#define TRACE_TASK_RUN(function, tag, task)
[email protected]3d3b37e92014-05-29 02:31:2328
29namespace cc {
30
mithro0c0ac6a2014-09-10 01:03:3631// TestOrderablePendingTask implementation
32TestOrderablePendingTask::TestOrderablePendingTask()
33 : base::TestPendingTask(),
34 task_id_(TestOrderablePendingTask::task_id_counter++) {
35}
36
37TestOrderablePendingTask::TestOrderablePendingTask(
38 const tracked_objects::Location& location,
tzik6e427842017-04-05 10:13:2139 base::OnceClosure task,
mithro0c0ac6a2014-09-10 01:03:3640 base::TimeTicks post_time,
41 base::TimeDelta delay,
42 TestNestability nestability)
tzik070c8ffb2017-03-29 05:28:1243 : base::TestPendingTask(location,
44 std::move(task),
45 post_time,
46 delay,
47 nestability),
48 task_id_(TestOrderablePendingTask::task_id_counter++) {}
mithro0c0ac6a2014-09-10 01:03:3649
tzika6f0007a2017-01-27 04:01:1150TestOrderablePendingTask::TestOrderablePendingTask(TestOrderablePendingTask&&) =
51 default;
52
53TestOrderablePendingTask& TestOrderablePendingTask::operator=(
54 TestOrderablePendingTask&&) = default;
55
mithro0c0ac6a2014-09-10 01:03:3656size_t TestOrderablePendingTask::task_id_counter = 0;
57
58TestOrderablePendingTask::~TestOrderablePendingTask() {
59}
60
61bool TestOrderablePendingTask::operator==(
62 const TestOrderablePendingTask& other) const {
63 return task_id_ == other.task_id_;
64}
65
66bool TestOrderablePendingTask::operator<(
67 const TestOrderablePendingTask& other) const {
68 if (*this == other)
69 return false;
70
71 if (GetTimeToRun() == other.GetTimeToRun()) {
72 return task_id_ < other.task_id_;
73 }
74 return ShouldRunBefore(other);
75}
76
danakj60bc3bc2016-04-09 00:24:4877std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
mithro0c0ac6a2014-09-10 01:03:3678TestOrderablePendingTask::AsValue() const {
danakj60bc3bc2016-04-09 00:24:4879 std::unique_ptr<base::trace_event::TracedValue> state(
primianocb1afb32016-02-29 20:46:0580 new base::trace_event::TracedValue());
mithro0c0ac6a2014-09-10 01:03:3681 AsValueInto(state.get());
primianocb1afb32016-02-29 20:46:0582 return std::move(state);
mithro0c0ac6a2014-09-10 01:03:3683}
84
85void TestOrderablePendingTask::AsValueInto(
ssid911e40e2015-02-09 17:55:2086 base::trace_event::TracedValue* state) const {
vmpstr45816062015-06-10 23:00:0087 state->SetInteger("id", base::saturated_cast<int>(task_id_));
mithro0c0ac6a2014-09-10 01:03:3688 state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
89 state->SetString("posted_from", location.ToString());
90}
91
mithro0c0ac6a2014-09-10 01:03:3692OrderedSimpleTaskRunner::OrderedSimpleTaskRunner(
ankur1.verma2e4c4e12015-06-13 13:38:2893 base::SimpleTestTickClock* now_src,
mithro0c0ac6a2014-09-10 01:03:3694 bool advance_now)
95 : advance_now_(advance_now),
96 now_src_(now_src),
97 max_tasks_(kAbsoluteMaxTasks),
98 inside_run_tasks_until_(false) {
99}
[email protected]3d3b37e92014-05-29 02:31:23100
101OrderedSimpleTaskRunner::~OrderedSimpleTaskRunner() {}
102
ankur1.verma2e4c4e12015-06-13 13:38:28103// static
104base::TimeTicks OrderedSimpleTaskRunner::AbsoluteMaxNow() {
105 return base::TimeTicks::FromInternalValue(
106 std::numeric_limits<int64_t>::max());
107}
108
mithro0c0ac6a2014-09-10 01:03:36109// base::TestSimpleTaskRunner implementation
110bool OrderedSimpleTaskRunner::PostDelayedTask(
111 const tracked_objects::Location& from_here,
tzik6e427842017-04-05 10:13:21112 base::OnceClosure task,
mithro0c0ac6a2014-09-10 01:03:36113 base::TimeDelta delay) {
[email protected]3d3b37e92014-05-29 02:31:23114 DCHECK(thread_checker_.CalledOnValidThread());
tzik070c8ffb2017-03-29 05:28:12115 TestOrderablePendingTask pt(from_here, std::move(task), now_src_->NowTicks(),
116 delay, base::TestPendingTask::NESTABLE);
mithro0c0ac6a2014-09-10 01:03:36117
118 TRACE_TASK("OrderedSimpleTaskRunner::PostDelayedTask", pt);
tzika6f0007a2017-01-27 04:01:11119 pending_tasks_.insert(std::move(pt));
mithro0c0ac6a2014-09-10 01:03:36120 return true;
121}
122
123bool OrderedSimpleTaskRunner::PostNonNestableDelayedTask(
124 const tracked_objects::Location& from_here,
tzik6e427842017-04-05 10:13:21125 base::OnceClosure task,
mithro0c0ac6a2014-09-10 01:03:36126 base::TimeDelta delay) {
127 DCHECK(thread_checker_.CalledOnValidThread());
tzik070c8ffb2017-03-29 05:28:12128 TestOrderablePendingTask pt(from_here, std::move(task), now_src_->NowTicks(),
129 delay, base::TestPendingTask::NON_NESTABLE);
mithro0c0ac6a2014-09-10 01:03:36130
131 TRACE_TASK("OrderedSimpleTaskRunner::PostNonNestableDelayedTask", pt);
tzika6f0007a2017-01-27 04:01:11132 pending_tasks_.insert(std::move(pt));
mithro0c0ac6a2014-09-10 01:03:36133 return true;
134}
135
136bool OrderedSimpleTaskRunner::RunsTasksOnCurrentThread() const {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 return true;
139}
140
alexclarke546ca222015-03-18 19:06:57141size_t OrderedSimpleTaskRunner::NumPendingTasks() const {
142 return pending_tasks_.size();
143}
144
mithroc34fc0b12014-09-30 09:10:41145bool OrderedSimpleTaskRunner::HasPendingTasks() const {
146 return pending_tasks_.size() > 0;
147}
148
mithro0c0ac6a2014-09-10 01:03:36149base::TimeTicks OrderedSimpleTaskRunner::NextTaskTime() {
alexclarkeeda1d2e2017-01-26 18:23:44150 RemoveCancelledTasks();
151
mithro0c0ac6a2014-09-10 01:03:36152 if (pending_tasks_.size() <= 0) {
ankur1.verma2e4c4e12015-06-13 13:38:28153 return AbsoluteMaxNow();
[email protected]3d3b37e92014-05-29 02:31:23154 }
mithro0c0ac6a2014-09-10 01:03:36155
156 return pending_tasks_.begin()->GetTimeToRun();
157}
158
159base::TimeDelta OrderedSimpleTaskRunner::DelayToNextTaskTime() {
160 DCHECK(thread_checker_.CalledOnValidThread());
alexclarkeeda1d2e2017-01-26 18:23:44161 RemoveCancelledTasks();
mithro0c0ac6a2014-09-10 01:03:36162
163 if (pending_tasks_.size() <= 0) {
ankur1.verma2e4c4e12015-06-13 13:38:28164 return AbsoluteMaxNow() - base::TimeTicks();
mithro0c0ac6a2014-09-10 01:03:36165 }
166
ankur1.verma2e4c4e12015-06-13 13:38:28167 base::TimeDelta delay = NextTaskTime() - now_src_->NowTicks();
mithro0c0ac6a2014-09-10 01:03:36168 if (delay > base::TimeDelta())
169 return delay;
170 return base::TimeDelta();
171}
172
173const size_t OrderedSimpleTaskRunner::kAbsoluteMaxTasks =
174 std::numeric_limits<size_t>::max();
175
176bool OrderedSimpleTaskRunner::RunTasksWhile(
177 base::Callback<bool(void)> condition) {
danakj6496cba2014-10-16 01:31:08178 std::vector<base::Callback<bool(void)>> conditions(1);
mithro0c0ac6a2014-09-10 01:03:36179 conditions[0] = condition;
180 return RunTasksWhile(conditions);
181}
182
183bool OrderedSimpleTaskRunner::RunTasksWhile(
danakj6496cba2014-10-16 01:31:08184 const std::vector<base::Callback<bool(void)>>& conditions) {
mithro0c0ac6a2014-09-10 01:03:36185 TRACE_EVENT2("cc",
186 "OrderedSimpleTaskRunner::RunPendingTasks",
187 "this",
188 AsValue(),
189 "nested",
190 inside_run_tasks_until_);
191 DCHECK(thread_checker_.CalledOnValidThread());
192
193 if (inside_run_tasks_until_)
194 return true;
195
196 base::AutoReset<bool> reset_inside_run_tasks_until_(&inside_run_tasks_until_,
197 true);
198
199 // Make a copy so we can append some extra run checks.
danakj6496cba2014-10-16 01:31:08200 std::vector<base::Callback<bool(void)>> modifiable_conditions(conditions);
mithro0c0ac6a2014-09-10 01:03:36201
202 // Provide a timeout base on number of tasks run so this doesn't loop
203 // forever.
204 modifiable_conditions.push_back(TaskRunCountBelow(max_tasks_));
205
206 // If to advance now or not
207 if (!advance_now_) {
ankur1.verma2e4c4e12015-06-13 13:38:28208 modifiable_conditions.push_back(NowBefore(now_src_->NowTicks()));
mithro0c0ac6a2014-09-10 01:03:36209 } else {
210 modifiable_conditions.push_back(AdvanceNow());
211 }
212
213 while (pending_tasks_.size() > 0) {
alexclarkeeda1d2e2017-01-26 18:23:44214 // Skip canceled tasks.
215 if (pending_tasks_.begin()->task.IsCancelled()) {
216 pending_tasks_.erase(pending_tasks_.begin());
217 continue;
218 }
mithro0c0ac6a2014-09-10 01:03:36219 // Check if we should continue to run pending tasks.
220 bool condition_success = true;
danakj6496cba2014-10-16 01:31:08221 for (std::vector<base::Callback<bool(void)>>::iterator it =
mithro0c0ac6a2014-09-10 01:03:36222 modifiable_conditions.begin();
223 it != modifiable_conditions.end();
224 it++) {
225 condition_success = it->Run();
226 if (!condition_success)
227 break;
228 }
229
230 // Conditions could modify the pending task length, so we need to recheck
231 // that there are tasks to run.
mithroc34fc0b12014-09-30 09:10:41232 if (!condition_success || !HasPendingTasks()) {
mithro0c0ac6a2014-09-10 01:03:36233 break;
234 }
235
236 std::set<TestOrderablePendingTask>::iterator task_to_run =
237 pending_tasks_.begin();
238 {
239 TRACE_EVENT1("cc",
240 "OrderedSimpleTaskRunner::RunPendingTasks running",
241 "task",
242 task_to_run->AsValue());
tzika6f0007a2017-01-27 04:01:11243 // It's safe to remove const and consume |task| here, since |task| is not
244 // used for ordering the item.
245 base::OnceClosure& task =
246 const_cast<base::OnceClosure&>(task_to_run->task);
247 std::move(task).Run();
mithro0c0ac6a2014-09-10 01:03:36248 }
249
250 pending_tasks_.erase(task_to_run);
251 }
252
mithroc34fc0b12014-09-30 09:10:41253 return HasPendingTasks();
mithro0c0ac6a2014-09-10 01:03:36254}
255
256bool OrderedSimpleTaskRunner::RunPendingTasks() {
257 return RunTasksWhile(TaskExistedInitially());
258}
259
260bool OrderedSimpleTaskRunner::RunUntilIdle() {
danakj6496cba2014-10-16 01:31:08261 return RunTasksWhile(std::vector<base::Callback<bool(void)>>());
mithro0c0ac6a2014-09-10 01:03:36262}
263
264bool OrderedSimpleTaskRunner::RunUntilTime(base::TimeTicks time) {
265 // If we are not auto advancing, force now forward to the time.
ankur1.verma2e4c4e12015-06-13 13:38:28266 if (!advance_now_ && now_src_->NowTicks() < time)
267 now_src_->Advance(time - now_src_->NowTicks());
mithro0c0ac6a2014-09-10 01:03:36268
269 // Run tasks
270 bool result = RunTasksWhile(NowBefore(time));
271
altimind8bd26c2016-11-04 11:44:54272 bool has_reached_task_limit = HasPendingTasks() && NextTaskTime() <= time;
273
mithro0c0ac6a2014-09-10 01:03:36274 // If the next task is after the stopping time and auto-advancing now, then
275 // force time to be the stopping time.
altimind8bd26c2016-11-04 11:44:54276 if (!has_reached_task_limit && advance_now_ && now_src_->NowTicks() < time) {
ankur1.verma2e4c4e12015-06-13 13:38:28277 now_src_->Advance(time - now_src_->NowTicks());
mithro0c0ac6a2014-09-10 01:03:36278 }
279
280 return result;
281}
282
283bool OrderedSimpleTaskRunner::RunForPeriod(base::TimeDelta period) {
ankur1.verma2e4c4e12015-06-13 13:38:28284 return RunUntilTime(now_src_->NowTicks() + period);
mithro0c0ac6a2014-09-10 01:03:36285}
286
ssid911e40e2015-02-09 17:55:20287// base::trace_event tracing functionality
danakj60bc3bc2016-04-09 00:24:48288std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
mithro0c0ac6a2014-09-10 01:03:36289OrderedSimpleTaskRunner::AsValue() const {
danakj60bc3bc2016-04-09 00:24:48290 std::unique_ptr<base::trace_event::TracedValue> state(
primianocb1afb32016-02-29 20:46:05291 new base::trace_event::TracedValue());
mithro0c0ac6a2014-09-10 01:03:36292 AsValueInto(state.get());
primianocb1afb32016-02-29 20:46:05293 return std::move(state);
mithro0c0ac6a2014-09-10 01:03:36294}
295
296void OrderedSimpleTaskRunner::AsValueInto(
ssid911e40e2015-02-09 17:55:20297 base::trace_event::TracedValue* state) const {
vmpstr45816062015-06-10 23:00:00298 state->SetInteger("pending_tasks",
299 base::saturated_cast<int>(pending_tasks_.size()));
mithro17a26f12014-10-09 11:30:04300
301 state->BeginArray("tasks");
mithro0c0ac6a2014-09-10 01:03:36302 for (std::set<TestOrderablePendingTask>::const_iterator it =
303 pending_tasks_.begin();
304 it != pending_tasks_.end();
305 ++it) {
mithro17a26f12014-10-09 11:30:04306 state->BeginDictionary();
mithro0c0ac6a2014-09-10 01:03:36307 it->AsValueInto(state);
308 state->EndDictionary();
309 }
mithro17a26f12014-10-09 11:30:04310 state->EndArray();
311
312 state->BeginDictionary("now_src");
ankur1.verma2e4c4e12015-06-13 13:38:28313 state->SetDouble("now_in_ms", (now_src_->NowTicks() - base::TimeTicks())
314 .InMillisecondsF());
mithro17a26f12014-10-09 11:30:04315 state->EndDictionary();
brianderson8eaf23b2015-05-15 00:24:05316
317 state->SetBoolean("advance_now", advance_now_);
318 state->SetBoolean("inside_run_tasks_until", inside_run_tasks_until_);
319 state->SetString("max_tasks", base::SizeTToString(max_tasks_));
mithro0c0ac6a2014-09-10 01:03:36320}
321
322base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskRunCountBelow(
323 size_t max_tasks) {
324 return base::Bind(&OrderedSimpleTaskRunner::TaskRunCountBelowCallback,
325 max_tasks,
326 base::Owned(new size_t(0)));
327}
328
329bool OrderedSimpleTaskRunner::TaskRunCountBelowCallback(size_t max_tasks,
330 size_t* tasks_run) {
331 return (*tasks_run)++ < max_tasks;
332}
333
334base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskExistedInitially() {
tzika6f0007a2017-01-27 04:01:11335 std::set<size_t> task_ids;
336 for (const auto& task : pending_tasks_)
337 task_ids.insert(task.task_id());
338
mithro0c0ac6a2014-09-10 01:03:36339 return base::Bind(&OrderedSimpleTaskRunner::TaskExistedInitiallyCallback,
tzika6f0007a2017-01-27 04:01:11340 base::Unretained(this), std::move(task_ids));
mithro0c0ac6a2014-09-10 01:03:36341}
342
343bool OrderedSimpleTaskRunner::TaskExistedInitiallyCallback(
tzika6f0007a2017-01-27 04:01:11344 const std::set<size_t>& existing_tasks) {
345 return existing_tasks.find(pending_tasks_.begin()->task_id()) !=
346 existing_tasks.end();
mithro0c0ac6a2014-09-10 01:03:36347}
348
349base::Callback<bool(void)> OrderedSimpleTaskRunner::NowBefore(
350 base::TimeTicks stop_at) {
351 return base::Bind(&OrderedSimpleTaskRunner::NowBeforeCallback,
352 base::Unretained(this),
353 stop_at);
354}
355bool OrderedSimpleTaskRunner::NowBeforeCallback(base::TimeTicks stop_at) {
356 return NextTaskTime() <= stop_at;
357}
358
359base::Callback<bool(void)> OrderedSimpleTaskRunner::AdvanceNow() {
360 return base::Bind(&OrderedSimpleTaskRunner::AdvanceNowCallback,
361 base::Unretained(this));
362}
363
364bool OrderedSimpleTaskRunner::AdvanceNowCallback() {
365 base::TimeTicks next_task_time = NextTaskTime();
ankur1.verma2e4c4e12015-06-13 13:38:28366 if (now_src_->NowTicks() < next_task_time) {
367 now_src_->Advance(next_task_time - now_src_->NowTicks());
mithro0c0ac6a2014-09-10 01:03:36368 }
369 return true;
[email protected]3d3b37e92014-05-29 02:31:23370}
371
alexclarkeeda1d2e2017-01-26 18:23:44372void OrderedSimpleTaskRunner::RemoveCancelledTasks() {
373 std::set<TestOrderablePendingTask>::iterator it = pending_tasks_.begin();
374 while (it != pending_tasks_.end()) {
375 if (it->task.IsCancelled()) {
376 it = pending_tasks_.erase(it);
377 } else {
378 it++;
379 }
380 }
381}
382
[email protected]3d3b37e92014-05-29 02:31:23383} // namespace cc