Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / test / ordered_simple_task_runner.cc
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.
4
5 #include "cc/test/ordered_simple_task_runner.h"
6
7 #include <limits>
8 #include <set>
9 #include <sstream>
10 #include <string>
11 #include <vector>
12
13 #include "base/auto_reset.h"
14 #include "base/debug/trace_event.h"
15 #include "base/debug/trace_event_argument.h"
16 #include "base/strings/string_number_conversions.h"
17
18 #define TRACE_TASK(function, task) \
19   TRACE_EVENT_INSTANT1(            \
20       "cc", function, TRACE_EVENT_SCOPE_THREAD, "task", task.AsValue());
21
22 #define TRACE_TASK_RUN(function, tag, task)
23
24 namespace cc {
25
26 // TestOrderablePendingTask implementation
27 TestOrderablePendingTask::TestOrderablePendingTask()
28     : base::TestPendingTask(),
29       task_id_(TestOrderablePendingTask::task_id_counter++) {
30 }
31
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++) {
40 }
41
42 size_t TestOrderablePendingTask::task_id_counter = 0;
43
44 TestOrderablePendingTask::~TestOrderablePendingTask() {
45 }
46
47 bool TestOrderablePendingTask::operator==(
48     const TestOrderablePendingTask& other) const {
49   return task_id_ == other.task_id_;
50 }
51
52 bool TestOrderablePendingTask::operator<(
53     const TestOrderablePendingTask& other) const {
54   if (*this == other)
55     return false;
56
57   if (GetTimeToRun() == other.GetTimeToRun()) {
58     return task_id_ < other.task_id_;
59   }
60   return ShouldRunBefore(other);
61 }
62
63 scoped_refptr<base::debug::ConvertableToTraceFormat>
64 TestOrderablePendingTask::AsValue() const {
65   scoped_refptr<base::debug::TracedValue> state =
66       new base::debug::TracedValue();
67   AsValueInto(state.get());
68   return state;
69 }
70
71 void TestOrderablePendingTask::AsValueInto(
72     base::debug::TracedValue* state) const {
73   state->SetInteger("id", task_id_);
74   state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
75   state->SetString("posted_from", location.ToString());
76 }
77
78 OrderedSimpleTaskRunner::OrderedSimpleTaskRunner()
79     : advance_now_(true),
80       now_src_(TestNowSource::Create(0)),
81       inside_run_tasks_until_(false) {
82 }
83
84 OrderedSimpleTaskRunner::OrderedSimpleTaskRunner(
85     scoped_refptr<TestNowSource> now_src,
86     bool advance_now)
87     : advance_now_(advance_now),
88       now_src_(now_src),
89       max_tasks_(kAbsoluteMaxTasks),
90       inside_run_tasks_until_(false) {
91 }
92
93 OrderedSimpleTaskRunner::~OrderedSimpleTaskRunner() {}
94
95 // base::TestSimpleTaskRunner implementation
96 bool OrderedSimpleTaskRunner::PostDelayedTask(
97     const tracked_objects::Location& from_here,
98     const base::Closure& task,
99     base::TimeDelta delay) {
100   DCHECK(thread_checker_.CalledOnValidThread());
101   TestOrderablePendingTask pt(
102       from_here, task, now_src_->Now(), delay, base::TestPendingTask::NESTABLE);
103
104   TRACE_TASK("OrderedSimpleTaskRunner::PostDelayedTask", pt);
105   pending_tasks_.insert(pt);
106   return true;
107 }
108
109 bool OrderedSimpleTaskRunner::PostNonNestableDelayedTask(
110     const tracked_objects::Location& from_here,
111     const base::Closure& task,
112     base::TimeDelta delay) {
113   DCHECK(thread_checker_.CalledOnValidThread());
114   TestOrderablePendingTask pt(from_here,
115                               task,
116                               now_src_->Now(),
117                               delay,
118                               base::TestPendingTask::NON_NESTABLE);
119
120   TRACE_TASK("OrderedSimpleTaskRunner::PostNonNestableDelayedTask", pt);
121   pending_tasks_.insert(pt);
122   return true;
123 }
124
125 bool OrderedSimpleTaskRunner::RunsTasksOnCurrentThread() const {
126   DCHECK(thread_checker_.CalledOnValidThread());
127   return true;
128 }
129
130 base::TimeTicks OrderedSimpleTaskRunner::NextTaskTime() {
131   if (pending_tasks_.size() <= 0) {
132     return TestNowSource::kAbsoluteMaxNow;
133   }
134
135   return pending_tasks_.begin()->GetTimeToRun();
136 }
137
138 base::TimeDelta OrderedSimpleTaskRunner::DelayToNextTaskTime() {
139   DCHECK(thread_checker_.CalledOnValidThread());
140
141   if (pending_tasks_.size() <= 0) {
142     return TestNowSource::kAbsoluteMaxNow - base::TimeTicks();
143   }
144
145   base::TimeDelta delay = NextTaskTime() - now_src_->Now();
146   if (delay > base::TimeDelta())
147     return delay;
148   return base::TimeDelta();
149 }
150
151 const size_t OrderedSimpleTaskRunner::kAbsoluteMaxTasks =
152     std::numeric_limits<size_t>::max();
153
154 bool OrderedSimpleTaskRunner::RunTasksWhile(
155     base::Callback<bool(void)> condition) {
156   std::vector<base::Callback<bool(void)> > conditions(1);
157   conditions[0] = condition;
158   return RunTasksWhile(conditions);
159 }
160
161 bool OrderedSimpleTaskRunner::RunTasksWhile(
162     const std::vector<base::Callback<bool(void)> >& conditions) {
163   TRACE_EVENT2("cc",
164                "OrderedSimpleTaskRunner::RunPendingTasks",
165                "this",
166                AsValue(),
167                "nested",
168                inside_run_tasks_until_);
169   DCHECK(thread_checker_.CalledOnValidThread());
170
171   if (inside_run_tasks_until_)
172     return true;
173
174   base::AutoReset<bool> reset_inside_run_tasks_until_(&inside_run_tasks_until_,
175                                                       true);
176
177   // Make a copy so we can append some extra run checks.
178   std::vector<base::Callback<bool(void)> > modifiable_conditions(conditions);
179
180   // Provide a timeout base on number of tasks run so this doesn't loop
181   // forever.
182   modifiable_conditions.push_back(TaskRunCountBelow(max_tasks_));
183
184   // If to advance now or not
185   if (!advance_now_) {
186     modifiable_conditions.push_back(NowBefore(now_src_->Now()));
187   } else {
188     modifiable_conditions.push_back(AdvanceNow());
189   }
190
191   while (pending_tasks_.size() > 0) {
192     // Check if we should continue to run pending tasks.
193     bool condition_success = true;
194     for (std::vector<base::Callback<bool(void)> >::iterator it =
195              modifiable_conditions.begin();
196          it != modifiable_conditions.end();
197          it++) {
198       condition_success = it->Run();
199       if (!condition_success)
200         break;
201     }
202
203     // Conditions could modify the pending task length, so we need to recheck
204     // that there are tasks to run.
205     if (!condition_success || pending_tasks_.size() == 0) {
206       break;
207     }
208
209     std::set<TestOrderablePendingTask>::iterator task_to_run =
210         pending_tasks_.begin();
211     {
212       TRACE_EVENT1("cc",
213                    "OrderedSimpleTaskRunner::RunPendingTasks running",
214                    "task",
215                    task_to_run->AsValue());
216       task_to_run->task.Run();
217     }
218
219     pending_tasks_.erase(task_to_run);
220   }
221
222   return pending_tasks_.size() > 0;
223 }
224
225 bool OrderedSimpleTaskRunner::RunPendingTasks() {
226   return RunTasksWhile(TaskExistedInitially());
227 }
228
229 bool OrderedSimpleTaskRunner::RunUntilIdle() {
230   return RunTasksWhile(std::vector<base::Callback<bool(void)> >());
231 }
232
233 bool OrderedSimpleTaskRunner::RunUntilTime(base::TimeTicks time) {
234   // If we are not auto advancing, force now forward to the time.
235   if (!advance_now_ && now_src_->Now() < time)
236     now_src_->SetNow(time);
237
238   // Run tasks
239   bool result = RunTasksWhile(NowBefore(time));
240
241   // If the next task is after the stopping time and auto-advancing now, then
242   // force time to be the stopping time.
243   if (!result && advance_now_ && now_src_->Now() < time) {
244     now_src_->SetNow(time);
245   }
246
247   return result;
248 }
249
250 bool OrderedSimpleTaskRunner::RunForPeriod(base::TimeDelta period) {
251   return RunUntilTime(now_src_->Now() + period);
252 }
253
254 // base::debug tracing functionality
255 scoped_refptr<base::debug::ConvertableToTraceFormat>
256 OrderedSimpleTaskRunner::AsValue() const {
257   scoped_refptr<base::debug::TracedValue> state =
258       new base::debug::TracedValue();
259   AsValueInto(state.get());
260   return state;
261 }
262
263 void OrderedSimpleTaskRunner::AsValueInto(
264     base::debug::TracedValue* state) const {
265   state->SetInteger("pending_tasks", pending_tasks_.size());
266   for (std::set<TestOrderablePendingTask>::const_iterator it =
267            pending_tasks_.begin();
268        it != pending_tasks_.end();
269        ++it) {
270     state->BeginDictionary(
271         base::SizeTToString(std::distance(pending_tasks_.begin(), it)).c_str());
272     it->AsValueInto(state);
273     state->EndDictionary();
274   }
275   now_src_->AsValueInto(state);
276 }
277
278 base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskRunCountBelow(
279     size_t max_tasks) {
280   return base::Bind(&OrderedSimpleTaskRunner::TaskRunCountBelowCallback,
281                     max_tasks,
282                     base::Owned(new size_t(0)));
283 }
284
285 bool OrderedSimpleTaskRunner::TaskRunCountBelowCallback(size_t max_tasks,
286                                                         size_t* tasks_run) {
287   return (*tasks_run)++ < max_tasks;
288 }
289
290 base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskExistedInitially() {
291   // base::Bind takes a copy of pending_tasks_
292   return base::Bind(&OrderedSimpleTaskRunner::TaskExistedInitiallyCallback,
293                     base::Unretained(this),
294                     pending_tasks_);
295 }
296
297 bool OrderedSimpleTaskRunner::TaskExistedInitiallyCallback(
298     const std::set<TestOrderablePendingTask>& existing_tasks) {
299   return existing_tasks.find(*pending_tasks_.begin()) != existing_tasks.end();
300 }
301
302 base::Callback<bool(void)> OrderedSimpleTaskRunner::NowBefore(
303     base::TimeTicks stop_at) {
304   return base::Bind(&OrderedSimpleTaskRunner::NowBeforeCallback,
305                     base::Unretained(this),
306                     stop_at);
307 }
308 bool OrderedSimpleTaskRunner::NowBeforeCallback(base::TimeTicks stop_at) {
309   return NextTaskTime() <= stop_at;
310 }
311
312 base::Callback<bool(void)> OrderedSimpleTaskRunner::AdvanceNow() {
313   return base::Bind(&OrderedSimpleTaskRunner::AdvanceNowCallback,
314                     base::Unretained(this));
315 }
316
317 bool OrderedSimpleTaskRunner::AdvanceNowCallback() {
318   base::TimeTicks next_task_time = NextTaskTime();
319   if (now_src_->Now() < next_task_time) {
320     now_src_->SetNow(next_task_time);
321   }
322   return true;
323 }
324
325 }  // namespace cc