Chromium Code Reviews| 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..3859dc116937cbf2624294473cf970b9d5649dd3 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(); |
|
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
|
| } |
| 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,20 @@ 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()); |
| + base::MessageLoop::current()->AddTaskObserver(task_observer); |
| + task_observers_.AddObserver(task_observer); |
| +} |
| + |
| +void TaskQueueManager::RemoveTaskObserver( |
| + base::MessageLoop::TaskObserver* task_observer) { |
| + DCHECK(main_thread_checker_.CalledOnValidThread()); |
| + base::MessageLoop::current()->RemoveTaskObserver(task_observer); |
| + task_observers_.RemoveObserver(task_observer); |
| +} |
| + |
| void TaskQueueManager::SetTimeSourceForTesting( |
| scoped_refptr<cc::TestNowSource> time_source) { |
| DCHECK(main_thread_checker_.CalledOnValidThread()); |