| Index: content/renderer/scheduler/task_queue_manager.cc
|
| diff --git a/content/renderer/scheduler/task_queue_manager.cc b/content/renderer/scheduler/task_queue_manager.cc
|
| index 112a37ca33c120b61319a12d587106335badfaf0..73b5ee2e480f07eb0390f3f4abc0f5b3ac6ea50a 100644
|
| --- a/content/renderer/scheduler/task_queue_manager.cc
|
| +++ b/content/renderer/scheduler/task_queue_manager.cc
|
| @@ -7,6 +7,7 @@
|
| #include <queue>
|
|
|
| #include "base/bind.h"
|
| +#include "base/observer_list.h"
|
| #include "base/trace_event/trace_event.h"
|
| #include "base/trace_event/trace_event_argument.h"
|
| #include "cc/test/test_now_source.h"
|
| @@ -274,6 +275,7 @@ TaskQueueManager::TaskQueueManager(
|
| pending_dowork_count_(0),
|
| work_batch_size_(1),
|
| time_source_(nullptr),
|
| + previous_task_(tracked_objects::Location(), base::Closure()),
|
| weak_factory_(this) {
|
| DCHECK(main_task_runner->RunsTasksOnCurrentThread());
|
| TRACE_EVENT_OBJECT_CREATED_WITH_ID(
|
| @@ -373,21 +375,22 @@ void TaskQueueManager::DoWork(bool posted_from_main_thread) {
|
| base::TimeTicks::FromInternalValue(kMaxTimeTicks));
|
| for (int i = 0; i < work_batch_size_; i++) {
|
| if (!UpdateWorkQueues(&next_pending_delayed_task))
|
| - return;
|
| + break;
|
|
|
| // Interrupt the work batch if we should run the next delayed task.
|
| if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks &&
|
| Now() >= next_pending_delayed_task)
|
| - return;
|
| + break;
|
|
|
| size_t queue_index;
|
| if (!SelectWorkQueueToService(&queue_index))
|
| - return;
|
| + break;
|
| // Note that this function won't post another call to DoWork if one is
|
| // already pending, so it is safe to call it in a loop.
|
| MaybePostDoWorkOnMainRunner();
|
| - ProcessTaskFromWorkQueue(queue_index);
|
| + ProcessTaskFromWorkQueue(queue_index, i == 0);
|
| }
|
| + previous_task_.task.Reset();
|
| }
|
|
|
| bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) {
|
| @@ -403,7 +406,8 @@ void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) {
|
| task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task);
|
| }
|
|
|
| -void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index) {
|
| +void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index,
|
| + bool first_task_in_batch) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| internal::TaskQueue* queue = Queue(queue_index);
|
| base::PendingTask pending_task = queue->TakeTaskFromWorkQueue();
|
| @@ -413,8 +417,18 @@ void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index) {
|
| main_task_runner_->PostNonNestableTask(pending_task.posted_from,
|
| pending_task.task);
|
| } else {
|
| + // Supress "will" task observer notifications for the first and "did"
|
| + // notifications for the last task in the batch to avoid duplicate
|
| + // notifications.
|
| + if (!first_task_in_batch) {
|
| + FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_,
|
| + DidProcessTask(previous_task_));
|
| + FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_,
|
| + WillProcessTask(pending_task));
|
| + }
|
| task_annotator_.RunTask("TaskQueueManager::PostTask",
|
| "TaskQueueManager::RunTask", pending_task);
|
| + previous_task_ = pending_task;
|
| }
|
| }
|
|
|
| @@ -442,6 +456,18 @@ void TaskQueueManager::SetWorkBatchSize(int work_batch_size) {
|
| work_batch_size_ = work_batch_size;
|
| }
|
|
|
| +void TaskQueueManager::AddTaskObserver(
|
| + base::MessageLoop::TaskObserver* task_observer) {
|
| + DCHECK(main_thread_checker_.CalledOnValidThread());
|
| + task_observers_.AddObserver(task_observer);
|
| +}
|
| +
|
| +void TaskQueueManager::RemoveTaskObserver(
|
| + base::MessageLoop::TaskObserver* task_observer) {
|
| + DCHECK(main_thread_checker_.CalledOnValidThread());
|
| + task_observers_.RemoveObserver(task_observer);
|
| +}
|
| +
|
| void TaskQueueManager::SetTimeSourceForTesting(
|
| scoped_refptr<cc::TestNowSource> time_source) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
|
|