Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Unified Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc

Issue 2546423002: [Try # 3] Scheduler refactoring to virtually eliminate redundant DoWorks (Closed)
Patch Set: Add an extra dcheck Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698