Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Side by Side Diff: components/scheduler/base/task_queue_manager.cc

Issue 1424053002: Adds a flag to support "Virtual Time" to the blink scheduler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added a test Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/scheduler/base/task_queue_manager.h" 5 #include "components/scheduler/base/task_queue_manager.h"
6 6
7 #include <queue> 7 #include <queue>
8 #include <set> 8 #include <set>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/time/default_tick_clock.h"
12 #include "components/scheduler/base/lazy_now.h" 11 #include "components/scheduler/base/lazy_now.h"
13 #include "components/scheduler/base/nestable_single_thread_task_runner.h" 12 #include "components/scheduler/base/nestable_single_thread_task_runner.h"
14 #include "components/scheduler/base/task_queue_impl.h" 13 #include "components/scheduler/base/task_queue_impl.h"
15 #include "components/scheduler/base/task_queue_selector.h" 14 #include "components/scheduler/base/task_queue_selector.h"
16 #include "components/scheduler/base/task_queue_sets.h" 15 #include "components/scheduler/base/task_queue_sets.h"
17 16
18 namespace { 17 namespace {
19 const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max(); 18 const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max();
20 } 19 }
21 20
22 namespace scheduler { 21 namespace scheduler {
23 22
24 TaskQueueManager::TaskQueueManager( 23 TaskQueueManager::TaskQueueManager(
25 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, 24 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner,
26 const char* tracing_category, 25 const char* tracing_category,
27 const char* disabled_by_default_tracing_category, 26 const char* disabled_by_default_tracing_category,
28 const char* disabled_by_default_verbose_tracing_category) 27 const char* disabled_by_default_verbose_tracing_category)
29 : main_task_runner_(main_task_runner), 28 : main_task_runner_(main_task_runner),
30 task_was_run_on_quiescence_monitored_queue_(false), 29 task_was_run_on_quiescence_monitored_queue_(false),
31 pending_dowork_count_(0), 30 pending_dowork_count_(0),
32 work_batch_size_(1), 31 work_batch_size_(1),
33 time_source_(new base::DefaultTickClock),
34 tracing_category_(tracing_category), 32 tracing_category_(tracing_category),
35 disabled_by_default_tracing_category_( 33 disabled_by_default_tracing_category_(
36 disabled_by_default_tracing_category), 34 disabled_by_default_tracing_category),
37 disabled_by_default_verbose_tracing_category_( 35 disabled_by_default_verbose_tracing_category_(
38 disabled_by_default_verbose_tracing_category), 36 disabled_by_default_verbose_tracing_category),
39 observer_(nullptr), 37 observer_(nullptr),
40 deletion_sentinel_(new DeletionSentinel()), 38 deletion_sentinel_(new DeletionSentinel()),
41 weak_factory_(this) { 39 weak_factory_(this) {
42 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); 40 DCHECK(main_task_runner->RunsTasksOnCurrentThread());
43 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, 41 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category,
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 newly_updatable_.pop_back(); 166 newly_updatable_.pop_back();
169 } 167 }
170 } 168 }
171 169
172 void TaskQueueManager::UpdateWorkQueues( 170 void TaskQueueManager::UpdateWorkQueues(
173 bool should_trigger_wakeup, 171 bool should_trigger_wakeup,
174 const internal::TaskQueueImpl::Task* previous_task) { 172 const internal::TaskQueueImpl::Task* previous_task) {
175 DCHECK(main_thread_checker_.CalledOnValidThread()); 173 DCHECK(main_thread_checker_.CalledOnValidThread());
176 TRACE_EVENT0(disabled_by_default_tracing_category_, 174 TRACE_EVENT0(disabled_by_default_tracing_category_,
177 "TaskQueueManager::UpdateWorkQueues"); 175 "TaskQueueManager::UpdateWorkQueues");
178 internal::LazyNow lazy_now(this); 176 internal::LazyNow lazy_now(tick_clock());
179 177
180 // Move any ready delayed tasks into the incomming queues. 178 // Move any ready delayed tasks into the incomming queues.
181 WakeupReadyDelayedQueues(&lazy_now); 179 WakeupReadyDelayedQueues(&lazy_now);
182 180
183 MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); 181 MoveNewlyUpdatableQueuesIntoUpdatableQueueSet();
184 182
185 auto iter = updatable_queue_set_.begin(); 183 auto iter = updatable_queue_set_.begin();
186 while (iter != updatable_queue_set_.end()) { 184 while (iter != updatable_queue_set_.end()) {
187 internal::TaskQueueImpl* queue = *iter++; 185 internal::TaskQueueImpl* queue = *iter++;
188 // NOTE Update work queue may erase itself from |updatable_queue_set_|. 186 // NOTE Update work queue may erase itself from |updatable_queue_set_|.
189 // This is fine, erasing an element won't invalidate any interator, as long 187 // This is fine, erasing an element won't invalidate any interator, as long
190 // as the iterator isn't the element being delated. 188 // as the iterator isn't the element being delated.
191 if (queue->work_queue().empty()) 189 if (queue->work_queue().empty())
192 queue->UpdateWorkQueue(&lazy_now, should_trigger_wakeup, previous_task); 190 queue->UpdateWorkQueue(&lazy_now, should_trigger_wakeup, previous_task);
193 } 191 }
194 } 192 }
195 193
196 void TaskQueueManager::ScheduleDelayedWorkTask( 194 void TaskQueueManager::ScheduleDelayedWorkTask(
197 scoped_refptr<internal::TaskQueueImpl> queue, 195 scoped_refptr<internal::TaskQueueImpl> queue,
198 base::TimeTicks delayed_run_time) { 196 base::TimeTicks delayed_run_time) {
199 internal::LazyNow lazy_now(this); 197 internal::LazyNow lazy_now(tick_clock());
200 ScheduleDelayedWork(queue.get(), delayed_run_time, &lazy_now); 198 ScheduleDelayedWork(queue.get(), delayed_run_time, &lazy_now);
201 } 199 }
202 200
203 void TaskQueueManager::ScheduleDelayedWork(internal::TaskQueueImpl* queue, 201 void TaskQueueManager::ScheduleDelayedWork(internal::TaskQueueImpl* queue,
204 base::TimeTicks delayed_run_time, 202 base::TimeTicks delayed_run_time,
205 internal::LazyNow* lazy_now) { 203 internal::LazyNow* lazy_now) {
206 if (!main_task_runner_->BelongsToCurrentThread()) { 204 if (!main_task_runner_->BelongsToCurrentThread()) {
207 // NOTE posting a delayed task from a different thread is not expected to be 205 // NOTE posting a delayed task from a different thread is not expected to be
208 // common. This pathway is less optimal than perhaps it could be because 206 // common. This pathway is less optimal than perhaps it could be because
209 // it causes two main thread tasks to be run. Should this assumption prove 207 // it causes two main thread tasks to be run. Should this assumption prove
(...skipping 15 matching lines...) Expand all
225 main_task_runner_->PostDelayedTask(FROM_HERE, delayed_queue_wakeup_closure_, 223 main_task_runner_->PostDelayedTask(FROM_HERE, delayed_queue_wakeup_closure_,
226 delay); 224 delay);
227 } 225 }
228 delayed_wakeup_multimap_.insert(std::make_pair(delayed_run_time, queue)); 226 delayed_wakeup_multimap_.insert(std::make_pair(delayed_run_time, queue));
229 } 227 }
230 228
231 void TaskQueueManager::DelayedDoWork() { 229 void TaskQueueManager::DelayedDoWork() {
232 DCHECK(main_thread_checker_.CalledOnValidThread()); 230 DCHECK(main_thread_checker_.CalledOnValidThread());
233 231
234 { 232 {
235 internal::LazyNow lazy_now(this); 233 internal::LazyNow lazy_now(tick_clock());
236 WakeupReadyDelayedQueues(&lazy_now); 234 WakeupReadyDelayedQueues(&lazy_now);
237 } 235 }
238 236
239 DoWork(false); 237 DoWork(false);
240 } 238 }
241 239
242 void TaskQueueManager::WakeupReadyDelayedQueues(internal::LazyNow* lazy_now) { 240 void TaskQueueManager::WakeupReadyDelayedQueues(internal::LazyNow* lazy_now) {
243 // Wake up any queues with pending delayed work. Note std::multipmap stores 241 // Wake up any queues with pending delayed work. Note std::multipmap stores
244 // the elements sorted by key, so the begin() iterator points to the earliest 242 // the elements sorted by key, so the begin() iterator points to the earliest
245 // queue to wakeup. 243 // queue to wakeup.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 310
313 // Only run a single task per batch in nested run loops so that we can 311 // Only run a single task per batch in nested run loops so that we can
314 // properly exit the nested loop when someone calls RunLoop::Quit(). 312 // properly exit the nested loop when someone calls RunLoop::Quit().
315 if (main_task_runner_->IsNested()) 313 if (main_task_runner_->IsNested())
316 break; 314 break;
317 } 315 }
318 316
319 // TODO(alexclarke): Consider refactoring the above loop to terminate only 317 // TODO(alexclarke): Consider refactoring the above loop to terminate only
320 // when there's no more work left to be done, rather than posting a 318 // when there's no more work left to be done, rather than posting a
321 // continuation task. 319 // continuation task.
322 if (!selector_.EnabledWorkQueuesEmpty()) 320 if (!selector_.EnabledWorkQueuesEmpty()) {
323 MaybePostDoWorkOnMainRunner(); 321 MaybePostDoWorkOnMainRunner();
322 } else {
323 // Tell the task runner we have no more work.
324 main_task_runner_->OnNoMoreWork();
325 }
324 } 326 }
325 327
326 bool TaskQueueManager::SelectQueueToService( 328 bool TaskQueueManager::SelectQueueToService(
327 internal::TaskQueueImpl** out_queue) { 329 internal::TaskQueueImpl** out_queue) {
328 bool should_run = selector_.SelectQueueToService(out_queue); 330 bool should_run = selector_.SelectQueueToService(out_queue);
329 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( 331 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
330 disabled_by_default_tracing_category_, "TaskQueueManager", this, 332 disabled_by_default_tracing_category_, "TaskQueueManager", this,
331 AsValueWithSelectorResult(should_run, *out_queue)); 333 AsValueWithSelectorResult(should_run, *out_queue));
332 return should_run; 334 return should_run;
333 } 335 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 DCHECK(main_thread_checker_.CalledOnValidThread()); 410 DCHECK(main_thread_checker_.CalledOnValidThread());
409 task_observers_.AddObserver(task_observer); 411 task_observers_.AddObserver(task_observer);
410 } 412 }
411 413
412 void TaskQueueManager::RemoveTaskObserver( 414 void TaskQueueManager::RemoveTaskObserver(
413 base::MessageLoop::TaskObserver* task_observer) { 415 base::MessageLoop::TaskObserver* task_observer) {
414 DCHECK(main_thread_checker_.CalledOnValidThread()); 416 DCHECK(main_thread_checker_.CalledOnValidThread());
415 task_observers_.RemoveObserver(task_observer); 417 task_observers_.RemoveObserver(task_observer);
416 } 418 }
417 419
418 void TaskQueueManager::SetTimeSourceForTesting(
419 scoped_ptr<base::TickClock> time_source) {
420 DCHECK(main_thread_checker_.CalledOnValidThread());
421 time_source_ = time_source.Pass();
422 }
423
424 bool TaskQueueManager::GetAndClearSystemIsQuiescentBit() { 420 bool TaskQueueManager::GetAndClearSystemIsQuiescentBit() {
425 bool task_was_run = task_was_run_on_quiescence_monitored_queue_; 421 bool task_was_run = task_was_run_on_quiescence_monitored_queue_;
426 task_was_run_on_quiescence_monitored_queue_ = false; 422 task_was_run_on_quiescence_monitored_queue_ = false;
427 return !task_was_run; 423 return !task_was_run;
428 } 424 }
429 425
430 base::TimeTicks TaskQueueManager::Now() const { 426 base::TickClock* TaskQueueManager::tick_clock() const {
431 return time_source_->NowTicks(); 427 return main_task_runner_.get();
432 } 428 }
433 429
434 int TaskQueueManager::GetNextSequenceNumber() { 430 int TaskQueueManager::GetNextSequenceNumber() {
435 return task_sequence_num_.GetNext(); 431 return task_sequence_num_.GetNext();
436 } 432 }
437 433
438 scoped_refptr<base::trace_event::ConvertableToTraceFormat> 434 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
439 TaskQueueManager::AsValueWithSelectorResult( 435 TaskQueueManager::AsValueWithSelectorResult(
440 bool should_run, 436 bool should_run,
441 internal::TaskQueueImpl* selected_queue) const { 437 internal::TaskQueueImpl* selected_queue) const {
(...skipping 18 matching lines...) Expand all
460 } 456 }
461 457
462 void TaskQueueManager::OnTaskQueueEnabled(internal::TaskQueueImpl* queue) { 458 void TaskQueueManager::OnTaskQueueEnabled(internal::TaskQueueImpl* queue) {
463 DCHECK(main_thread_checker_.CalledOnValidThread()); 459 DCHECK(main_thread_checker_.CalledOnValidThread());
464 // Only schedule DoWork if there's something to do. 460 // Only schedule DoWork if there's something to do.
465 if (!queue->work_queue().empty()) 461 if (!queue->work_queue().empty())
466 MaybePostDoWorkOnMainRunner(); 462 MaybePostDoWorkOnMainRunner();
467 } 463 }
468 464
469 } // namespace scheduler 465 } // namespace scheduler
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698