| 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 a0bc14200139e176ee03b6dccefa0d8a29270d67..7ef94420f8acce312fe2bd791d89714d75d30aa1 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
|
| @@ -154,8 +154,11 @@ TaskQueueImpl::MainThreadOnly::MainThreadOnly(
|
| TimeDomain* time_domain)
|
| : task_queue_manager(task_queue_manager),
|
| time_domain(time_domain),
|
| - delayed_work_queue(new WorkQueue(task_queue, "delayed")),
|
| - immediate_work_queue(new WorkQueue(task_queue, "immediate")),
|
| + delayed_work_queue(
|
| + new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)),
|
| + immediate_work_queue(new WorkQueue(task_queue,
|
| + "immediate",
|
| + WorkQueue::QueueType::IMMEDIATE)),
|
| set_index(0),
|
| is_enabled_refcount(0),
|
| voter_refcount(0),
|
| @@ -183,7 +186,6 @@ void TaskQueueImpl::UnregisterTaskQueue() {
|
| }
|
|
|
| bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
|
| - base::AutoLock lock(any_thread_lock_);
|
| return base::PlatformThread::CurrentId() == thread_id_;
|
| }
|
|
|
| @@ -325,19 +327,17 @@ void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(
|
| base::TimeTicks desired_run_time,
|
| EnqueueOrder sequence_number,
|
| bool nestable) {
|
| - if (any_thread().immediate_incoming_queue.empty())
|
| - any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
|
| // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
|
| // it run.
|
| if (any_thread().immediate_incoming_queue.empty()) {
|
| - // There's no point posting a DoWork for a disabled queue, however we can
|
| - // only tell if it's disabled from the main thread.
|
| - if (base::PlatformThread::CurrentId() == thread_id_) {
|
| - if (IsQueueEnabled() && !BlockedByFenceLocked())
|
| - any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
|
| - } else {
|
| - any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
|
| - }
|
| + // There's no point posting a DoWork for a blocked or disabled queue,
|
| + // although we can only determine that on the main thread.
|
| + bool ensure_do_work_posted =
|
| + !RunsTasksOnCurrentThread() ||
|
| + (IsQueueEnabled() && !main_thread_only().current_fence);
|
| + any_thread().task_queue_manager->OnQueueHasIncomingImmediateWork(
|
| + this, ensure_do_work_posted);
|
| + any_thread().time_domain->OnQueueHasImmediateWork(this);
|
| }
|
| any_thread().immediate_incoming_queue.emplace_back(
|
| posted_from, task, desired_run_time, sequence_number, nestable,
|
| @@ -347,6 +347,20 @@ void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(
|
| TraceQueueSize(true);
|
| }
|
|
|
| +void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() {
|
| + if (!main_thread_only().immediate_work_queue->Empty())
|
| + return;
|
| +
|
| + main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue();
|
| +}
|
| +
|
| +WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() {
|
| + base::AutoLock lock(any_thread_lock_);
|
| + WTF::Deque<TaskQueueImpl::Task> queue;
|
| + queue.swap(any_thread().immediate_incoming_queue);
|
| + return queue;
|
| +}
|
| +
|
| bool TaskQueueImpl::IsEmpty() const {
|
| if (!main_thread_only().delayed_work_queue->Empty() ||
|
| !main_thread_only().delayed_incoming_queue.empty() ||
|
| @@ -396,7 +410,8 @@ base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() {
|
| return main_thread_only().delayed_incoming_queue.top().delayed_run_time;
|
| }
|
|
|
| -void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) {
|
| +base::Optional<base::TimeTicks> TaskQueueImpl::WakeUpForDelayedWork(
|
| + LazyNow* lazy_now) {
|
| // Enqueue all delayed tasks that should be running now, skipping any that
|
| // have been canceled.
|
| while (!main_thread_only().delayed_incoming_queue.empty()) {
|
| @@ -415,25 +430,10 @@ void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) {
|
| }
|
|
|
| // Make sure the next wake up is scheduled.
|
| - 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,
|
| - lazy_now->Now());
|
| - }
|
| -}
|
| -
|
| -bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() {
|
| - if (!main_thread_only().task_queue_manager)
|
| - return false;
|
| -
|
| - if (!main_thread_only().immediate_work_queue->Empty())
|
| - return true;
|
| + if (!main_thread_only().delayed_incoming_queue.empty())
|
| + return main_thread_only().delayed_incoming_queue.top().delayed_run_time;
|
|
|
| - base::AutoLock lock(any_thread_lock_);
|
| - main_thread_only().immediate_work_queue->SwapLocked(
|
| - any_thread().immediate_incoming_queue);
|
| - // |immediate_work_queue| is now empty so updates are no longer required.
|
| - return false;
|
| + return base::Optional<base::TimeTicks>();
|
| }
|
|
|
| void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
|
| @@ -576,10 +576,13 @@ void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) {
|
|
|
| any_thread().time_domain = time_domain;
|
| }
|
| - // We rely here on TimeDomain::MigrateQueue being thread-safe to use with
|
| - // TimeDomain::Register/UnregisterAsUpdatableTaskQueue.
|
| - main_thread_only().time_domain->MigrateQueue(this, time_domain);
|
| +
|
| + base::TimeTicks wake_up_time =
|
| + main_thread_only().time_domain->MigrateQueue(this, time_domain);
|
| main_thread_only().time_domain = time_domain;
|
| +
|
| + if (!wake_up_time.is_null())
|
| + time_domain->ScheduleDelayedWork(this, wake_up_time, time_domain->Now());
|
| }
|
|
|
| TimeDomain* TaskQueueImpl::GetTimeDomain() const {
|
| @@ -672,19 +675,20 @@ bool TaskQueueImpl::BlockedByFence() const {
|
| main_thread_only().current_fence;
|
| }
|
|
|
| -bool TaskQueueImpl::BlockedByFenceLocked() const {
|
| - if (!main_thread_only().current_fence)
|
| +bool TaskQueueImpl::ImmediateTaskCouldRun() const {
|
| + if (!IsQueueEnabled())
|
| return false;
|
|
|
| - if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
|
| - !main_thread_only().delayed_work_queue->BlockedByFence()) {
|
| - return false;
|
| - }
|
| + if (!main_thread_only().current_fence)
|
| + return true;
|
|
|
| + base::AutoLock lock(any_thread_lock_);
|
| + // If |immediate_incoming_queue| is empty then any task posted is guaranteed
|
| + // to be blocked by the fence.
|
| if (any_thread().immediate_incoming_queue.empty())
|
| - return true;
|
| + return false;
|
|
|
| - return any_thread().immediate_incoming_queue.front().enqueue_order() >
|
| + return any_thread().immediate_incoming_queue.front().enqueue_order() <
|
| main_thread_only().current_fence;
|
| }
|
|
|
| @@ -799,8 +803,8 @@ void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) {
|
| return;
|
|
|
| if (enable) {
|
| - // Note it's the job of the selector to tell the TaskQueueManager if
|
| - // a DoWork needs posting.
|
| + // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts
|
| + // a DoWork if needed.
|
| main_thread_only().task_queue_manager->selector_.EnableQueue(this);
|
| } else {
|
| main_thread_only().task_queue_manager->selector_.DisableQueue(this);
|
| @@ -821,19 +825,33 @@ void TaskQueueImpl::SweepCanceledDelayedTasks(base::TimeTicks now) {
|
| base::TimeTicks first_task_runtime =
|
| main_thread_only().delayed_incoming_queue.top().delayed_run_time;
|
|
|
| - // TODO(alexclarke): Let this remove all tasks once the DoWork refactor has
|
| - // landed.
|
| + // Remove canceled tasks.
|
| std::priority_queue<Task> remaining_tasks;
|
| while (!main_thread_only().delayed_incoming_queue.empty()) {
|
| - if (!main_thread_only().delayed_incoming_queue.top().task.IsCancelled() ||
|
| - main_thread_only().delayed_incoming_queue.top().delayed_run_time ==
|
| - first_task_runtime) {
|
| + if (!main_thread_only().delayed_incoming_queue.top().task.IsCancelled()) {
|
| remaining_tasks.push(std::move(
|
| const_cast<Task&>(main_thread_only().delayed_incoming_queue.top())));
|
| }
|
| main_thread_only().delayed_incoming_queue.pop();
|
| }
|
| +
|
| main_thread_only().delayed_incoming_queue = std::move(remaining_tasks);
|
| +
|
| + // Re-schedule delayed call to WakeUpForDelayedWork if needed.
|
| + if (main_thread_only().delayed_incoming_queue.empty()) {
|
| + main_thread_only().time_domain->CancelDelayedWork(this);
|
| + } else if (first_task_runtime !=
|
| + main_thread_only().delayed_incoming_queue.top().delayed_run_time) {
|
| + main_thread_only().time_domain->ScheduleDelayedWork(
|
| + this, main_thread_only().delayed_incoming_queue.top().delayed_run_time,
|
| + main_thread_only().time_domain->Now());
|
| + }
|
| +}
|
| +
|
| +void TaskQueueImpl::PushImmediateIncomingTaskForTest(
|
| + TaskQueueImpl::Task&& task) {
|
| + base::AutoLock lock(any_thread_lock_);
|
| + any_thread().immediate_incoming_queue.push_back(std::move(task));
|
| }
|
|
|
| } // namespace internal
|
|
|