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

Side by Side Diff: content/renderer/scheduler/task_queue_manager.cc

Issue 922733002: scheduler: Implement task observers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added comment about callback counts. Created 5 years, 9 months 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 "content/renderer/scheduler/task_queue_manager.h" 5 #include "content/renderer/scheduler/task_queue_manager.h"
6 6
7 #include <queue> 7 #include <queue>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/observer_list.h"
10 #include "base/trace_event/trace_event.h" 11 #include "base/trace_event/trace_event.h"
11 #include "base/trace_event/trace_event_argument.h" 12 #include "base/trace_event/trace_event_argument.h"
12 #include "cc/test/test_now_source.h" 13 #include "cc/test/test_now_source.h"
13 #include "content/renderer/scheduler/task_queue_selector.h" 14 #include "content/renderer/scheduler/task_queue_selector.h"
14 15
15 namespace { 16 namespace {
16 const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max(); 17 const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max();
17 } 18 }
18 19
19 namespace content { 20 namespace content {
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 268
268 TaskQueueManager::TaskQueueManager( 269 TaskQueueManager::TaskQueueManager(
269 size_t task_queue_count, 270 size_t task_queue_count,
270 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 271 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
271 TaskQueueSelector* selector) 272 TaskQueueSelector* selector)
272 : main_task_runner_(main_task_runner), 273 : main_task_runner_(main_task_runner),
273 selector_(selector), 274 selector_(selector),
274 pending_dowork_count_(0), 275 pending_dowork_count_(0),
275 work_batch_size_(1), 276 work_batch_size_(1),
276 time_source_(nullptr), 277 time_source_(nullptr),
278 previous_task_(tracked_objects::Location(), base::Closure()),
277 weak_factory_(this) { 279 weak_factory_(this) {
278 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); 280 DCHECK(main_task_runner->RunsTasksOnCurrentThread());
279 TRACE_EVENT_OBJECT_CREATED_WITH_ID( 281 TRACE_EVENT_OBJECT_CREATED_WITH_ID(
280 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", 282 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager",
281 this); 283 this);
282 284
283 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); 285 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr();
284 for (size_t i = 0; i < task_queue_count; i++) { 286 for (size_t i = 0; i < task_queue_count; i++) {
285 scoped_refptr<internal::TaskQueue> queue( 287 scoped_refptr<internal::TaskQueue> queue(
286 make_scoped_refptr(new internal::TaskQueue(this))); 288 make_scoped_refptr(new internal::TaskQueue(this)));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 if (posted_from_main_thread) { 368 if (posted_from_main_thread) {
367 pending_dowork_count_--; 369 pending_dowork_count_--;
368 DCHECK_GE(pending_dowork_count_, 0); 370 DCHECK_GE(pending_dowork_count_, 0);
369 } 371 }
370 DCHECK(main_thread_checker_.CalledOnValidThread()); 372 DCHECK(main_thread_checker_.CalledOnValidThread());
371 373
372 base::TimeTicks next_pending_delayed_task( 374 base::TimeTicks next_pending_delayed_task(
373 base::TimeTicks::FromInternalValue(kMaxTimeTicks)); 375 base::TimeTicks::FromInternalValue(kMaxTimeTicks));
374 for (int i = 0; i < work_batch_size_; i++) { 376 for (int i = 0; i < work_batch_size_; i++) {
375 if (!UpdateWorkQueues(&next_pending_delayed_task)) 377 if (!UpdateWorkQueues(&next_pending_delayed_task))
376 return; 378 break;
377 379
378 // Interrupt the work batch if we should run the next delayed task. 380 // Interrupt the work batch if we should run the next delayed task.
379 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks && 381 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks &&
380 Now() >= next_pending_delayed_task) 382 Now() >= next_pending_delayed_task)
381 return; 383 break;
382 384
383 size_t queue_index; 385 size_t queue_index;
384 if (!SelectWorkQueueToService(&queue_index)) 386 if (!SelectWorkQueueToService(&queue_index))
385 return; 387 break;
386 // Note that this function won't post another call to DoWork if one is 388 // Note that this function won't post another call to DoWork if one is
387 // already pending, so it is safe to call it in a loop. 389 // already pending, so it is safe to call it in a loop.
388 MaybePostDoWorkOnMainRunner(); 390 MaybePostDoWorkOnMainRunner();
389 ProcessTaskFromWorkQueue(queue_index); 391 ProcessTaskFromWorkQueue(queue_index, i == 0);
390 } 392 }
393 previous_task_.task.Reset();
rmcilroy 2015/02/24 15:32:00 One last nit (feel free to ignore) - could you jus
Sami 2015/02/24 17:04:43 I wanted to avoid heap allocations and made it a m
391 } 394 }
392 395
393 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { 396 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) {
394 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); 397 bool should_run = selector_->SelectWorkQueueToService(out_queue_index);
395 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( 398 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
396 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this, 399 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this,
397 AsValueWithSelectorResult(should_run, *out_queue_index)); 400 AsValueWithSelectorResult(should_run, *out_queue_index));
398 return should_run; 401 return should_run;
399 } 402 }
400 403
401 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { 404 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) {
402 pending_task->sequence_num = task_sequence_num_.GetNext(); 405 pending_task->sequence_num = task_sequence_num_.GetNext();
403 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); 406 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task);
404 } 407 }
405 408
406 void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index) { 409 void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index,
410 bool first_task_in_batch) {
407 DCHECK(main_thread_checker_.CalledOnValidThread()); 411 DCHECK(main_thread_checker_.CalledOnValidThread());
408 internal::TaskQueue* queue = Queue(queue_index); 412 internal::TaskQueue* queue = Queue(queue_index);
409 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); 413 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue();
410 if (!pending_task.nestable) { 414 if (!pending_task.nestable) {
411 // Defer non-nestable work to the main task runner. NOTE these tasks can be 415 // Defer non-nestable work to the main task runner. NOTE these tasks can be
412 // arbitrarily delayed so the additional delay should not be a problem. 416 // arbitrarily delayed so the additional delay should not be a problem.
413 main_task_runner_->PostNonNestableTask(pending_task.posted_from, 417 main_task_runner_->PostNonNestableTask(pending_task.posted_from,
414 pending_task.task); 418 pending_task.task);
415 } else { 419 } else {
420 // Supress "will" task observer notifications for the first and "did"
421 // notifications for the last task in the batch to avoid duplicate
422 // notifications.
423 if (!first_task_in_batch) {
424 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_,
425 DidProcessTask(previous_task_));
426 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_,
427 WillProcessTask(pending_task));
428 }
416 task_annotator_.RunTask("TaskQueueManager::PostTask", 429 task_annotator_.RunTask("TaskQueueManager::PostTask",
417 "TaskQueueManager::RunTask", pending_task); 430 "TaskQueueManager::RunTask", pending_task);
431 previous_task_ = pending_task;
418 } 432 }
419 } 433 }
420 434
421 bool TaskQueueManager::RunsTasksOnCurrentThread() const { 435 bool TaskQueueManager::RunsTasksOnCurrentThread() const {
422 return main_task_runner_->RunsTasksOnCurrentThread(); 436 return main_task_runner_->RunsTasksOnCurrentThread();
423 } 437 }
424 438
425 bool TaskQueueManager::PostDelayedTask( 439 bool TaskQueueManager::PostDelayedTask(
426 const tracked_objects::Location& from_here, 440 const tracked_objects::Location& from_here,
427 const base::Closure& task, 441 const base::Closure& task,
428 base::TimeDelta delay) { 442 base::TimeDelta delay) {
429 DCHECK(delay > base::TimeDelta()); 443 DCHECK(delay > base::TimeDelta());
430 return main_task_runner_->PostDelayedTask(from_here, task, delay); 444 return main_task_runner_->PostDelayedTask(from_here, task, delay);
431 } 445 }
432 446
433 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { 447 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) {
434 DCHECK(main_thread_checker_.CalledOnValidThread()); 448 DCHECK(main_thread_checker_.CalledOnValidThread());
435 internal::TaskQueue* queue = Queue(queue_index); 449 internal::TaskQueue* queue = Queue(queue_index);
436 queue->set_name(name); 450 queue->set_name(name);
437 } 451 }
438 452
439 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { 453 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) {
440 DCHECK(main_thread_checker_.CalledOnValidThread()); 454 DCHECK(main_thread_checker_.CalledOnValidThread());
441 DCHECK_GE(work_batch_size, 1); 455 DCHECK_GE(work_batch_size, 1);
442 work_batch_size_ = work_batch_size; 456 work_batch_size_ = work_batch_size;
443 } 457 }
444 458
459 void TaskQueueManager::AddTaskObserver(
460 base::MessageLoop::TaskObserver* task_observer) {
461 DCHECK(main_thread_checker_.CalledOnValidThread());
462 base::MessageLoop::current()->AddTaskObserver(task_observer);
463 task_observers_.AddObserver(task_observer);
464 }
465
466 void TaskQueueManager::RemoveTaskObserver(
467 base::MessageLoop::TaskObserver* task_observer) {
468 DCHECK(main_thread_checker_.CalledOnValidThread());
469 base::MessageLoop::current()->RemoveTaskObserver(task_observer);
470 task_observers_.RemoveObserver(task_observer);
471 }
472
445 void TaskQueueManager::SetTimeSourceForTesting( 473 void TaskQueueManager::SetTimeSourceForTesting(
446 scoped_refptr<cc::TestNowSource> time_source) { 474 scoped_refptr<cc::TestNowSource> time_source) {
447 DCHECK(main_thread_checker_.CalledOnValidThread()); 475 DCHECK(main_thread_checker_.CalledOnValidThread());
448 time_source_ = time_source; 476 time_source_ = time_source;
449 } 477 }
450 478
451 base::TimeTicks TaskQueueManager::Now() const { 479 base::TimeTicks TaskQueueManager::Now() const {
452 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); 480 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now();
453 } 481 }
454 482
455 scoped_refptr<base::trace_event::ConvertableToTraceFormat> 483 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
456 TaskQueueManager::AsValueWithSelectorResult(bool should_run, 484 TaskQueueManager::AsValueWithSelectorResult(bool should_run,
457 size_t selected_queue) const { 485 size_t selected_queue) const {
458 DCHECK(main_thread_checker_.CalledOnValidThread()); 486 DCHECK(main_thread_checker_.CalledOnValidThread());
459 scoped_refptr<base::trace_event::TracedValue> state = 487 scoped_refptr<base::trace_event::TracedValue> state =
460 new base::trace_event::TracedValue(); 488 new base::trace_event::TracedValue();
461 state->BeginArray("queues"); 489 state->BeginArray("queues");
462 for (auto& queue : queues_) 490 for (auto& queue : queues_)
463 queue->AsValueInto(state.get()); 491 queue->AsValueInto(state.get());
464 state->EndArray(); 492 state->EndArray();
465 state->BeginDictionary("selector"); 493 state->BeginDictionary("selector");
466 selector_->AsValueInto(state.get()); 494 selector_->AsValueInto(state.get());
467 state->EndDictionary(); 495 state->EndDictionary();
468 if (should_run) 496 if (should_run)
469 state->SetInteger("selected_queue", selected_queue); 497 state->SetInteger("selected_queue", selected_queue);
470 return state; 498 return state;
471 } 499 }
472 500
473 } // namespace content 501 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/scheduler/task_queue_manager.h ('k') | content/renderer/scheduler/task_queue_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698