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

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: Build fix. 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/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 DCHECK_GE(pending_dowork_count_, 0); 412 DCHECK_GE(pending_dowork_count_, 0);
413 } 413 }
414 DCHECK(main_thread_checker_.CalledOnValidThread()); 414 DCHECK(main_thread_checker_.CalledOnValidThread());
415 415
416 base::TimeTicks next_pending_delayed_task( 416 base::TimeTicks next_pending_delayed_task(
417 base::TimeTicks::FromInternalValue(kMaxTimeTicks)); 417 base::TimeTicks::FromInternalValue(kMaxTimeTicks));
418 418
419 if (!UpdateWorkQueues(&next_pending_delayed_task, BEFORE_WAKEUP_EVENT_TYPE)) 419 if (!UpdateWorkQueues(&next_pending_delayed_task, BEFORE_WAKEUP_EVENT_TYPE))
420 return; 420 return;
421 421
422 base::PendingTask previous_task((tracked_objects::Location()),
423 (base::Closure()));
422 for (int i = 0; i < work_batch_size_; i++) { 424 for (int i = 0; i < work_batch_size_; i++) {
423 // Interrupt the work batch if we should run the next delayed task. 425 // Interrupt the work batch if we should run the next delayed task.
424 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks && 426 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks &&
425 Now() >= next_pending_delayed_task) 427 Now() >= next_pending_delayed_task)
426 return; 428 return;
427 429
428 size_t queue_index; 430 size_t queue_index;
429 if (!SelectWorkQueueToService(&queue_index)) 431 if (!SelectWorkQueueToService(&queue_index))
430 return; 432 return;
431 // Note that this function won't post another call to DoWork if one is 433 // Note that this function won't post another call to DoWork if one is
432 // already pending, so it is safe to call it in a loop. 434 // already pending, so it is safe to call it in a loop.
433 MaybePostDoWorkOnMainRunner(); 435 MaybePostDoWorkOnMainRunner();
434 ProcessTaskFromWorkQueue(queue_index); 436 ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task);
435 437
436 if (!UpdateWorkQueues(&next_pending_delayed_task, AFTER_WAKEUP_EVENT_TYPE)) 438 if (!UpdateWorkQueues(&next_pending_delayed_task, AFTER_WAKEUP_EVENT_TYPE))
437 return; 439 return;
438 } 440 }
439 } 441 }
440 442
441 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { 443 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) {
442 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); 444 bool should_run = selector_->SelectWorkQueueToService(out_queue_index);
443 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( 445 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
444 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this, 446 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this,
445 AsValueWithSelectorResult(should_run, *out_queue_index)); 447 AsValueWithSelectorResult(should_run, *out_queue_index));
446 return should_run; 448 return should_run;
447 } 449 }
448 450
449 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { 451 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) {
450 pending_task->sequence_num = task_sequence_num_.GetNext(); 452 pending_task->sequence_num = task_sequence_num_.GetNext();
451 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); 453 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task);
452 } 454 }
453 455
454 void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index) { 456 void TaskQueueManager::ProcessTaskFromWorkQueue(
457 size_t queue_index,
458 bool has_previous_task,
459 base::PendingTask* previous_task) {
455 DCHECK(main_thread_checker_.CalledOnValidThread()); 460 DCHECK(main_thread_checker_.CalledOnValidThread());
456 internal::TaskQueue* queue = Queue(queue_index); 461 internal::TaskQueue* queue = Queue(queue_index);
457 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); 462 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue();
458 if (!pending_task.nestable) { 463 if (!pending_task.nestable) {
459 // Defer non-nestable work to the main task runner. NOTE these tasks can be 464 // Defer non-nestable work to the main task runner. NOTE these tasks can be
460 // arbitrarily delayed so the additional delay should not be a problem. 465 // arbitrarily delayed so the additional delay should not be a problem.
461 main_task_runner_->PostNonNestableTask(pending_task.posted_from, 466 main_task_runner_->PostNonNestableTask(pending_task.posted_from,
462 pending_task.task); 467 pending_task.task);
463 } else { 468 } else {
469 // Suppress "will" task observer notifications for the first and "did"
470 // notifications for the last task in the batch to avoid duplicate
471 // notifications.
472 if (has_previous_task) {
473 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_,
474 DidProcessTask(*previous_task));
475 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_,
476 WillProcessTask(pending_task));
477 }
464 task_annotator_.RunTask("TaskQueueManager::PostTask", 478 task_annotator_.RunTask("TaskQueueManager::PostTask",
465 "TaskQueueManager::RunTask", pending_task); 479 "TaskQueueManager::RunTask", pending_task);
480 pending_task.task.Reset();
481 *previous_task = pending_task;
466 } 482 }
467 } 483 }
468 484
469 bool TaskQueueManager::RunsTasksOnCurrentThread() const { 485 bool TaskQueueManager::RunsTasksOnCurrentThread() const {
470 return main_task_runner_->RunsTasksOnCurrentThread(); 486 return main_task_runner_->RunsTasksOnCurrentThread();
471 } 487 }
472 488
473 bool TaskQueueManager::PostDelayedTask( 489 bool TaskQueueManager::PostDelayedTask(
474 const tracked_objects::Location& from_here, 490 const tracked_objects::Location& from_here,
475 const base::Closure& task, 491 const base::Closure& task,
476 base::TimeDelta delay) { 492 base::TimeDelta delay) {
477 DCHECK(delay > base::TimeDelta()); 493 DCHECK(delay > base::TimeDelta());
478 return main_task_runner_->PostDelayedTask(from_here, task, delay); 494 return main_task_runner_->PostDelayedTask(from_here, task, delay);
479 } 495 }
480 496
481 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { 497 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) {
482 DCHECK(main_thread_checker_.CalledOnValidThread()); 498 DCHECK(main_thread_checker_.CalledOnValidThread());
483 internal::TaskQueue* queue = Queue(queue_index); 499 internal::TaskQueue* queue = Queue(queue_index);
484 queue->set_name(name); 500 queue->set_name(name);
485 } 501 }
486 502
487 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { 503 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) {
488 DCHECK(main_thread_checker_.CalledOnValidThread()); 504 DCHECK(main_thread_checker_.CalledOnValidThread());
489 DCHECK_GE(work_batch_size, 1); 505 DCHECK_GE(work_batch_size, 1);
490 work_batch_size_ = work_batch_size; 506 work_batch_size_ = work_batch_size;
491 } 507 }
492 508
509 void TaskQueueManager::AddTaskObserver(
510 base::MessageLoop::TaskObserver* task_observer) {
511 DCHECK(main_thread_checker_.CalledOnValidThread());
512 base::MessageLoop::current()->AddTaskObserver(task_observer);
513 task_observers_.AddObserver(task_observer);
514 }
515
516 void TaskQueueManager::RemoveTaskObserver(
517 base::MessageLoop::TaskObserver* task_observer) {
518 DCHECK(main_thread_checker_.CalledOnValidThread());
519 base::MessageLoop::current()->RemoveTaskObserver(task_observer);
520 task_observers_.RemoveObserver(task_observer);
521 }
522
493 void TaskQueueManager::SetTimeSourceForTesting( 523 void TaskQueueManager::SetTimeSourceForTesting(
494 scoped_refptr<cc::TestNowSource> time_source) { 524 scoped_refptr<cc::TestNowSource> time_source) {
495 DCHECK(main_thread_checker_.CalledOnValidThread()); 525 DCHECK(main_thread_checker_.CalledOnValidThread());
496 time_source_ = time_source; 526 time_source_ = time_source;
497 } 527 }
498 528
499 base::TimeTicks TaskQueueManager::Now() const { 529 base::TimeTicks TaskQueueManager::Now() const {
500 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); 530 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now();
501 } 531 }
502 532
503 scoped_refptr<base::trace_event::ConvertableToTraceFormat> 533 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
504 TaskQueueManager::AsValueWithSelectorResult(bool should_run, 534 TaskQueueManager::AsValueWithSelectorResult(bool should_run,
505 size_t selected_queue) const { 535 size_t selected_queue) const {
506 DCHECK(main_thread_checker_.CalledOnValidThread()); 536 DCHECK(main_thread_checker_.CalledOnValidThread());
507 scoped_refptr<base::trace_event::TracedValue> state = 537 scoped_refptr<base::trace_event::TracedValue> state =
508 new base::trace_event::TracedValue(); 538 new base::trace_event::TracedValue();
509 state->BeginArray("queues"); 539 state->BeginArray("queues");
510 for (auto& queue : queues_) 540 for (auto& queue : queues_)
511 queue->AsValueInto(state.get()); 541 queue->AsValueInto(state.get());
512 state->EndArray(); 542 state->EndArray();
513 state->BeginDictionary("selector"); 543 state->BeginDictionary("selector");
514 selector_->AsValueInto(state.get()); 544 selector_->AsValueInto(state.get());
515 state->EndDictionary(); 545 state->EndDictionary();
516 if (should_run) 546 if (should_run)
517 state->SetInteger("selected_queue", selected_queue); 547 state->SetInteger("selected_queue", selected_queue);
518 return state; 548 return state;
519 } 549 }
520 550
521 } // namespace content 551 } // 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