Chromium Code Reviews| Index: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc |
| diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc |
| index f0758bae6e5793818902f518ec407e5c2d5a4072..429125d2f7b63808929395621f2caac6cd5a7d90 100644 |
| --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc |
| +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc |
| @@ -103,6 +103,8 @@ TaskQueueImpl::~TaskQueueImpl() { |
| DCHECK(any_thread().task_queue_manager == nullptr) |
| << "UnregisterTaskQueue must be called first!"; |
| + DCHECK(any_thread().observer == nullptr) |
| + << "TaskQueue::Observer must be unregistered manually!"; |
|
Sami
2017/04/05 13:16:51
The above DCHECK covers this, right? Looks like th
altimin
2017/04/05 13:55:18
Done.
|
| #endif |
| } |
| @@ -147,7 +149,9 @@ TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, |
| TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
| TimeDomain* time_domain) |
| - : task_queue_manager(task_queue_manager), time_domain(time_domain) {} |
| + : task_queue_manager(task_queue_manager), |
| + time_domain(time_domain), |
| + observer(nullptr) {} |
| TaskQueueImpl::AnyThread::~AnyThread() {} |
| @@ -157,6 +161,7 @@ TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
| TimeDomain* time_domain) |
| : task_queue_manager(task_queue_manager), |
| time_domain(time_domain), |
| + observer(nullptr), |
| delayed_work_queue( |
| new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)), |
| immediate_work_queue(new WorkQueue(task_queue, |
| @@ -183,6 +188,8 @@ void TaskQueueImpl::UnregisterTaskQueue() { |
| any_thread().task_queue_manager = nullptr; |
| main_thread_only().task_queue_manager = nullptr; |
| + any_thread().observer = nullptr; |
| + main_thread_only().observer = nullptr; |
| main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); |
| immediate_incoming_queue().clear(); |
| main_thread_only().immediate_work_queue.reset(); |
| @@ -277,19 +284,15 @@ bool TaskQueueImpl::PostDelayedTaskImpl( |
| void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( |
| Task pending_task, base::TimeTicks now) { |
| - base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
| + DelayedWakeUp wake_up = pending_task.delayed_wake_up(); |
| main_thread_only().task_queue_manager->DidQueueTask(pending_task); |
| main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); |
| - // If |pending_task| is at the head of the queue, then make sure a wakeup |
| - // is requested if the queue is enabled. Note we still want to schedule a |
| - // wakeup even if blocked by a fence, because we'd break throttling logic |
| - // otherwise. |
| - base::TimeTicks next_delayed_task = |
| - main_thread_only().delayed_incoming_queue.top().delayed_run_time; |
| - if (next_delayed_task == delayed_run_time && IsQueueEnabled()) { |
| - main_thread_only().time_domain->ScheduleDelayedWork( |
| - this, {delayed_run_time, pending_task.sequence_num}, now); |
| + DelayedWakeUp new_wake_up = |
| + main_thread_only().delayed_incoming_queue.top().delayed_wake_up(); |
| + if (wake_up.time == new_wake_up.time && |
|
Sami
2017/04/05 13:16:51
This could use a comment saying what we're doing h
altimin
2017/04/05 13:55:18
Done. We need it because we need to update TimeDom
Sami
2017/04/05 14:38:15
Does this cause a new wake-up to be scheduled at t
altimin
2017/04/05 15:10:22
No, TQM::MaybeScheduleDelayedWork tracks that for
|
| + wake_up.sequence_num == new_wake_up.sequence_num) { |
| + ScheduleDelayedWorkInTimeDomain(now); |
| } |
| TraceQueueSize(); |
| @@ -358,7 +361,8 @@ void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( |
| (!IsQueueEnabled() || main_thread_only().current_fence); |
| any_thread().task_queue_manager->OnQueueHasIncomingImmediateWork( |
| this, sequence_number, queue_is_blocked); |
| - any_thread().time_domain->OnQueueHasImmediateWork(this); |
| + if (any_thread().observer) |
| + any_thread().observer->OnQueueNextWakeUpChanged(this, desired_run_time); |
| } |
| TraceQueueSize(); |
| @@ -421,7 +425,7 @@ bool TaskQueueImpl::HasPendingImmediateWork() const { |
| } |
| base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { |
| - // Note we don't scheduled a wakeup for disabled queues. |
| + // Note we don't scheduled a wake_up for disabled queues. |
|
Sami
2017/04/05 13:16:51
s/scheduled/schedule/ since you're changing this :
altimin
2017/04/05 13:55:18
Done.
|
| if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) |
| return base::nullopt; |
| @@ -449,9 +453,7 @@ TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) { |
| // Make sure the next wake up is scheduled. |
| if (!main_thread_only().delayed_incoming_queue.empty()) { |
| - return DelayedWakeUp{ |
| - main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| - main_thread_only().delayed_incoming_queue.top().sequence_num}; |
| + return main_thread_only().delayed_incoming_queue.top().delayed_wake_up(); |
| } |
| return base::nullopt; |
| @@ -598,13 +600,7 @@ void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) { |
| main_thread_only().time_domain = time_domain; |
| time_domain->RegisterQueue(this); |
| - if (IsQueueEnabled() && !main_thread_only().delayed_incoming_queue.empty()) { |
| - time_domain->ScheduleDelayedWork( |
| - this, |
| - {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| - main_thread_only().delayed_incoming_queue.top().sequence_num}, |
| - time_domain->Now()); |
| - } |
| + ScheduleDelayedWorkInTimeDomain(time_domain->Now()); |
| } |
| TimeDomain* TaskQueueImpl::GetTimeDomain() const { |
| @@ -816,24 +812,11 @@ void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { |
| return; |
| if (enable) { |
| - // Check if there's any immediate work on either queue. |
| - bool immediate_queues_empty = |
| - main_thread_only().immediate_work_queue->Empty(); |
| - if (immediate_queues_empty) { |
| - base::AutoLock lock(immediate_incoming_queue_lock_); |
| - immediate_queues_empty = immediate_incoming_queue().empty(); |
| - } |
| - // Avoid holding the lock while we fire the notification. |
| - if (!immediate_queues_empty) |
| - main_thread_only().time_domain->OnQueueHasImmediateWork(this); |
| - |
| - if (!main_thread_only().delayed_incoming_queue.empty()) { |
| - main_thread_only().time_domain->ScheduleDelayedWork( |
| - this, |
| - {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| - main_thread_only().delayed_incoming_queue.top().sequence_num}, |
| - main_thread_only().time_domain->Now()); |
| - } |
| + if (HasPendingImmediateWork()) |
| + NotifyWakeUpChangedOnMainThread(base::TimeTicks()); |
| + |
| + ScheduleDelayedWorkInTimeDomain(main_thread_only().time_domain->Now()); |
| + |
| // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts |
| // a DoWork if needed. |
| main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
| @@ -875,13 +858,7 @@ void TaskQueueImpl::SweepCanceledDelayedTasks(base::TimeTicks now) { |
| main_thread_only().time_domain->CancelDelayedWork(this); |
| } else if (first_task_runtime != |
| main_thread_only().delayed_incoming_queue.top().delayed_run_time) { |
| - if (IsQueueEnabled()) { |
| - main_thread_only().time_domain->ScheduleDelayedWork( |
| - this, |
| - {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| - main_thread_only().delayed_incoming_queue.top().sequence_num}, |
| - main_thread_only().time_domain->Now()); |
| - } |
| + ScheduleDelayedWorkInTimeDomain(main_thread_only().time_domain->Now()); |
| } |
| } |
| @@ -891,6 +868,39 @@ void TaskQueueImpl::PushImmediateIncomingTaskForTest( |
| immediate_incoming_queue().push_back(std::move(task)); |
| } |
| +void TaskQueueImpl::SetObserver(Observer* observer) { |
| +#if DCHECK_IS_ON() |
| + if (observer) |
|
Sami
2017/04/05 13:16:51
nit: braces
altimin
2017/04/05 13:55:18
Done.
|
| + DCHECK(!main_thread_only().observer) << "Can't assign two different " |
| + "observers to " |
| + "blink::scheduler::TaskQueue"; |
| +#endif |
| + base::AutoLock lock(any_thread_lock_); |
| + any_thread().observer = observer; |
| + main_thread_only().observer = observer; |
| +} |
| + |
| +void TaskQueueImpl::ScheduleDelayedWorkInTimeDomain(base::TimeTicks now) { |
| + if (!IsQueueEnabled()) |
| + return; |
| + if (main_thread_only().delayed_incoming_queue.empty()) |
| + return; |
| + |
| + main_thread_only().time_domain->ScheduleDelayedWork( |
| + this, main_thread_only().delayed_incoming_queue.top().delayed_wake_up(), |
| + now); |
| + |
| + if (!HasPendingImmediateWork()) { |
| + NotifyWakeUpChangedOnMainThread( |
| + main_thread_only().delayed_incoming_queue.top().delayed_run_time); |
| + } |
| +} |
| + |
| +void TaskQueueImpl::NotifyWakeUpChangedOnMainThread(base::TimeTicks wake_up) { |
| + if (main_thread_only().observer) |
| + main_thread_only().observer->OnQueueNextWakeUpChanged(this, wake_up); |
| +} |
| + |
| } // namespace internal |
| } // namespace scheduler |
| } // namespace blink |