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 f4f8fc5f8f28a2ee01e57836107ff7658dab50df..0b88d5a2f3791534dc5ac0c0f3a36014d1bbb9a5 100644 |
--- a/content/renderer/scheduler/task_queue_manager.cc |
+++ b/content/renderer/scheduler/task_queue_manager.cc |
@@ -43,7 +43,7 @@ class TaskQueue : public base::SingleThreadTaskRunner { |
void PumpQueue(); |
bool UpdateWorkQueue(base::TimeTicks* next_pending_delayed_task, |
- TaskQueueManager::WorkQueueUpdateEventType event_type); |
+ const base::PendingTask* previous_task); |
base::PendingTask TakeTaskFromWorkQueue(); |
void WillDeleteTaskQueueManager(); |
@@ -73,8 +73,8 @@ class TaskQueue : public base::SingleThreadTaskRunner { |
void EnqueueTask(const base::PendingTask& pending_task); |
void PumpQueueLocked(); |
- bool ShouldAutoPumpQueueLocked( |
- TaskQueueManager::WorkQueueUpdateEventType event_type); |
+ bool TaskIsOlderThanQueuedTasks(const base::PendingTask* task); |
+ bool ShouldAutoPumpQueueLocked(const base::PendingTask* previous_task); |
void EnqueueTaskLocked(const base::PendingTask& pending_task); |
void TraceQueueSize(bool is_locked) const; |
@@ -153,13 +153,35 @@ bool TaskQueue::IsQueueEmpty() const { |
} |
} |
+bool TaskQueue::TaskIsOlderThanQueuedTasks(const base::PendingTask* task) { |
+ lock_.AssertAcquired(); |
+ // A null task is passed when UpdateQueue is called before any task is run. |
+ // In this case we don't want to pump an after_wakeup queue, so return true |
+ // here. |
+ if (!task) |
+ return true; |
+ |
+ // Return false if there are no task in the incoming queue. |
+ if (incoming_queue_.empty()) |
+ return false; |
+ |
+ base::PendingTask oldest_queued_task = incoming_queue_.front(); |
+ DCHECK(oldest_queued_task.delayed_run_time.is_null()); |
+ DCHECK(task->delayed_run_time.is_null()); |
+ |
+ // Note: the comparison is correct due to the fact that the PendingTask |
+ // operator inverts its comparison operation in order to work well in a heap |
+ // based priority queue. |
+ return oldest_queued_task < *task; |
+} |
+ |
bool TaskQueue::ShouldAutoPumpQueueLocked( |
- TaskQueueManager::WorkQueueUpdateEventType event_type) { |
+ const base::PendingTask* previous_task) { |
lock_.AssertAcquired(); |
if (pump_policy_ == TaskQueueManager::PumpPolicy::MANUAL) |
return false; |
if (pump_policy_ == TaskQueueManager::PumpPolicy::AFTER_WAKEUP && |
- event_type != TaskQueueManager::WorkQueueUpdateEventType::AFTER_WAKEUP) |
+ TaskIsOlderThanQueuedTasks(previous_task)) |
return false; |
if (incoming_queue_.empty()) |
return false; |
@@ -168,7 +190,7 @@ bool TaskQueue::ShouldAutoPumpQueueLocked( |
bool TaskQueue::UpdateWorkQueue( |
base::TimeTicks* next_pending_delayed_task, |
- TaskQueueManager::WorkQueueUpdateEventType event_type) { |
+ const base::PendingTask* previous_task) { |
if (!work_queue_.empty()) |
return true; |
@@ -178,7 +200,7 @@ bool TaskQueue::UpdateWorkQueue( |
*next_pending_delayed_task = |
std::min(*next_pending_delayed_task, delayed_task_run_times_.top()); |
} |
- if (!ShouldAutoPumpQueueLocked(event_type)) |
+ if (!ShouldAutoPumpQueueLocked(previous_task)) |
return false; |
work_queue_.Swap(&incoming_queue_); |
TraceQueueSize(true); |
@@ -383,14 +405,15 @@ void TaskQueueManager::PumpQueue(size_t queue_index) { |
bool TaskQueueManager::UpdateWorkQueues( |
base::TimeTicks* next_pending_delayed_task, |
- WorkQueueUpdateEventType event_type) { |
+ const base::PendingTask* previous_task) { |
// TODO(skyostil): This is not efficient when the number of queues grows very |
// large due to the number of locks taken. Consider optimizing when we get |
// there. |
DCHECK(main_thread_checker_.CalledOnValidThread()); |
bool has_work = false; |
for (auto& queue : queues_) { |
- has_work |= queue->UpdateWorkQueue(next_pending_delayed_task, event_type); |
+ has_work |= queue->UpdateWorkQueue(next_pending_delayed_task, |
+ previous_task); |
if (!queue->work_queue().empty()) { |
// Currently we should not be getting tasks with delayed run times in any |
// of the work queues. |
@@ -426,8 +449,9 @@ void TaskQueueManager::DoWork(bool posted_from_main_thread) { |
base::TimeTicks next_pending_delayed_task( |
base::TimeTicks::FromInternalValue(kMaxTimeTicks)); |
- if (!UpdateWorkQueues(&next_pending_delayed_task, |
- WorkQueueUpdateEventType::BEFORE_WAKEUP)) |
+ // Pass nullptr to UpdateWorkQueues here to prevent waking up an |
+ // pump-after-wakeup queue. |
+ if (!UpdateWorkQueues(&next_pending_delayed_task, nullptr)) |
return; |
base::PendingTask previous_task((tracked_objects::Location()), |
@@ -446,8 +470,7 @@ void TaskQueueManager::DoWork(bool posted_from_main_thread) { |
MaybePostDoWorkOnMainRunner(); |
ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task); |
- if (!UpdateWorkQueues(&next_pending_delayed_task, |
- WorkQueueUpdateEventType::AFTER_WAKEUP)) |
+ if (!UpdateWorkQueues(&next_pending_delayed_task, &previous_task)) |
return; |
} |
} |