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

Side by Side 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: Rebased Created 4 years 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/scheduler/base/task_queue_impl.h" 5 #include "platform/scheduler/base/task_queue_impl.h"
6 6
7 #include "base/format_macros.h" 7 #include "base/format_macros.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
10 #include "base/trace_event/blame_context.h" 10 #include "base/trace_event/blame_context.h"
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 : task_queue_manager(task_queue_manager), time_domain(time_domain) {} 147 : task_queue_manager(task_queue_manager), time_domain(time_domain) {}
148 148
149 TaskQueueImpl::AnyThread::~AnyThread() {} 149 TaskQueueImpl::AnyThread::~AnyThread() {}
150 150
151 TaskQueueImpl::MainThreadOnly::MainThreadOnly( 151 TaskQueueImpl::MainThreadOnly::MainThreadOnly(
152 TaskQueueManager* task_queue_manager, 152 TaskQueueManager* task_queue_manager,
153 TaskQueueImpl* task_queue, 153 TaskQueueImpl* task_queue,
154 TimeDomain* time_domain) 154 TimeDomain* time_domain)
155 : task_queue_manager(task_queue_manager), 155 : task_queue_manager(task_queue_manager),
156 time_domain(time_domain), 156 time_domain(time_domain),
157 delayed_work_queue(new WorkQueue(task_queue, "delayed")), 157 delayed_work_queue(
158 immediate_work_queue(new WorkQueue(task_queue, "immediate")), 158 new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)),
159 immediate_work_queue(new WorkQueue(task_queue,
160 "immediate",
161 WorkQueue::QueueType::IMMEDIATE)),
159 set_index(0), 162 set_index(0),
160 is_enabled_refcount(0), 163 is_enabled_refcount(0),
161 voter_refcount(0), 164 voter_refcount(0),
162 blame_context(nullptr), 165 blame_context(nullptr),
163 current_fence(0) {} 166 current_fence(0) {}
164 167
165 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} 168 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
166 169
167 void TaskQueueImpl::UnregisterTaskQueue() { 170 void TaskQueueImpl::UnregisterTaskQueue() {
168 base::AutoLock lock(any_thread_lock_); 171 base::AutoLock lock(any_thread_lock_);
169 if (main_thread_only().time_domain) 172 if (main_thread_only().time_domain)
170 main_thread_only().time_domain->UnregisterQueue(this); 173 main_thread_only().time_domain->UnregisterQueue(this);
171 if (!any_thread().task_queue_manager) 174 if (!any_thread().task_queue_manager)
172 return; 175 return;
173 any_thread().time_domain = nullptr; 176 any_thread().time_domain = nullptr;
174 main_thread_only().time_domain = nullptr; 177 main_thread_only().time_domain = nullptr;
175 any_thread().task_queue_manager->UnregisterTaskQueue(this); 178 any_thread().task_queue_manager->UnregisterTaskQueue(this);
176 179
177 any_thread().task_queue_manager = nullptr; 180 any_thread().task_queue_manager = nullptr;
178 main_thread_only().task_queue_manager = nullptr; 181 main_thread_only().task_queue_manager = nullptr;
179 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); 182 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>();
180 any_thread().immediate_incoming_queue = std::queue<Task>(); 183 any_thread().immediate_incoming_queue = std::queue<Task>();
181 main_thread_only().immediate_work_queue.reset(); 184 main_thread_only().immediate_work_queue.reset();
182 main_thread_only().delayed_work_queue.reset(); 185 main_thread_only().delayed_work_queue.reset();
183 } 186 }
184 187
185 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { 188 bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
186 base::AutoLock lock(any_thread_lock_);
187 return base::PlatformThread::CurrentId() == thread_id_; 189 return base::PlatformThread::CurrentId() == thread_id_;
188 } 190 }
189 191
190 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, 192 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here,
191 const base::Closure& task, 193 const base::Closure& task,
192 base::TimeDelta delay) { 194 base::TimeDelta delay) {
193 if (delay.is_zero()) 195 if (delay.is_zero())
194 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); 196 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL);
195 197
196 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); 198 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 } 320 }
319 TraceQueueSize(false); 321 TraceQueueSize(false);
320 } 322 }
321 323
322 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( 324 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(
323 const tracked_objects::Location& posted_from, 325 const tracked_objects::Location& posted_from,
324 const base::Closure& task, 326 const base::Closure& task,
325 base::TimeTicks desired_run_time, 327 base::TimeTicks desired_run_time,
326 EnqueueOrder sequence_number, 328 EnqueueOrder sequence_number,
327 bool nestable) { 329 bool nestable) {
328 if (any_thread().immediate_incoming_queue.empty())
329 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
330 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make 330 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
331 // it run. 331 // it run.
332 if (any_thread().immediate_incoming_queue.empty()) { 332 if (any_thread().immediate_incoming_queue.empty()) {
333 // There's no point posting a DoWork for a disabled queue, however we can 333 // There's no point posting a DoWork for a blocked or disabled queue,
334 // only tell if it's disabled from the main thread. 334 // although we can only determine that on the main thread.
335 if (base::PlatformThread::CurrentId() == thread_id_) { 335 bool ensure_do_work_posted = !RunsTasksOnCurrentThread() ||
336 if (IsQueueEnabled() && !BlockedByFenceLocked()) 336 (IsQueueEnabled() && !BlockedByFenceLocked());
337 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 337 any_thread().task_queue_manager->OnQueueHasImmediateWork(
338 } else { 338 this, ensure_do_work_posted);
339 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 339 any_thread().time_domain->OnQueueHasImmediateWork(this);
340 }
341 } 340 }
341
342 any_thread().immediate_incoming_queue.emplace( 342 any_thread().immediate_incoming_queue.emplace(
343 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); 343 posted_from, task, desired_run_time, sequence_number, nestable,
344 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back()); 344 sequence_number);
345 any_thread().task_queue_manager->DidQueueTask(
346 any_thread().immediate_incoming_queue.back());
345 TraceQueueSize(true); 347 TraceQueueSize(true);
346 } 348 }
347 349
350 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() {
351 if (!main_thread_only().immediate_work_queue->Empty())
352 return;
353
354 base::AutoLock lock(any_thread_lock_);
355 if (any_thread().immediate_incoming_queue.empty())
356 return;
357
358 main_thread_only().immediate_work_queue->SwapLocked(
359 any_thread().immediate_incoming_queue);
360 }
361
362 void TaskQueueImpl::OnImmediateWorkQueueHasBecomeEmpty(
363 std::queue<TaskQueueImpl::Task>* work_queue) {
364 base::AutoLock lock(any_thread_lock_);
365 DCHECK(work_queue->empty());
366
367 if (any_thread().immediate_incoming_queue.empty())
368 return;
369
370 std::swap(any_thread().immediate_incoming_queue, *work_queue);
371 }
372
348 bool TaskQueueImpl::IsEmpty() const { 373 bool TaskQueueImpl::IsEmpty() const {
349 if (!main_thread_only().delayed_work_queue->Empty() || 374 if (!main_thread_only().delayed_work_queue->Empty() ||
350 !main_thread_only().delayed_incoming_queue.empty() || 375 !main_thread_only().delayed_incoming_queue.empty() ||
351 !main_thread_only().immediate_work_queue->Empty()) { 376 !main_thread_only().immediate_work_queue->Empty()) {
352 return false; 377 return false;
353 } 378 }
354 379
355 base::AutoLock lock(any_thread_lock_); 380 base::AutoLock lock(any_thread_lock_);
356 return any_thread().immediate_incoming_queue.empty(); 381 return any_thread().immediate_incoming_queue.empty();
357 } 382 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 } 438 }
414 439
415 // Make sure the next wake up is scheduled. 440 // Make sure the next wake up is scheduled.
416 if (!main_thread_only().delayed_incoming_queue.empty()) { 441 if (!main_thread_only().delayed_incoming_queue.empty()) {
417 main_thread_only().time_domain->ScheduleDelayedWork( 442 main_thread_only().time_domain->ScheduleDelayedWork(
418 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, 443 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time,
419 lazy_now->Now()); 444 lazy_now->Now());
420 } 445 }
421 } 446 }
422 447
423 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() {
424 if (!main_thread_only().task_queue_manager)
425 return false;
426
427 if (!main_thread_only().immediate_work_queue->Empty())
428 return true;
429
430 base::AutoLock lock(any_thread_lock_);
431 main_thread_only().immediate_work_queue->SwapLocked(
432 any_thread().immediate_incoming_queue);
433 // |immediate_work_queue| is now empty so updates are no longer required.
434 return false;
435 }
436
437 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { 448 void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
438 bool is_tracing; 449 bool is_tracing;
439 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, 450 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
440 &is_tracing); 451 &is_tracing);
441 if (!is_tracing) 452 if (!is_tracing)
442 return; 453 return;
443 454
444 // It's only safe to access the work queues from the main thread. 455 // It's only safe to access the work queues from the main thread.
445 // TODO(alexclarke): We should find another way of tracing this 456 // TODO(alexclarke): We should find another way of tracing this
446 if (base::PlatformThread::CurrentId() != thread_id_) 457 if (base::PlatformThread::CurrentId() != thread_id_)
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 // another way of asserting that UnregisterTaskQueue has not been called. 578 // another way of asserting that UnregisterTaskQueue has not been called.
568 DCHECK(any_thread().time_domain); 579 DCHECK(any_thread().time_domain);
569 if (!any_thread().time_domain) 580 if (!any_thread().time_domain)
570 return; 581 return;
571 DCHECK(main_thread_checker_.CalledOnValidThread()); 582 DCHECK(main_thread_checker_.CalledOnValidThread());
572 if (time_domain == main_thread_only().time_domain) 583 if (time_domain == main_thread_only().time_domain)
573 return; 584 return;
574 585
575 any_thread().time_domain = time_domain; 586 any_thread().time_domain = time_domain;
576 } 587 }
577 // We rely here on TimeDomain::MigrateQueue being thread-safe to use with 588
578 // TimeDomain::Register/UnregisterAsUpdatableTaskQueue.
579 main_thread_only().time_domain->MigrateQueue(this, time_domain); 589 main_thread_only().time_domain->MigrateQueue(this, time_domain);
580 main_thread_only().time_domain = time_domain; 590 main_thread_only().time_domain = time_domain;
581 } 591 }
582 592
583 TimeDomain* TaskQueueImpl::GetTimeDomain() const { 593 TimeDomain* TaskQueueImpl::GetTimeDomain() const {
584 if (base::PlatformThread::CurrentId() == thread_id_) 594 if (base::PlatformThread::CurrentId() == thread_id_)
585 return main_thread_only().time_domain; 595 return main_thread_only().time_domain;
586 596
587 base::AutoLock lock(any_thread_lock_); 597 base::AutoLock lock(any_thread_lock_);
588 return any_thread().time_domain; 598 return any_thread().time_domain;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 674
665 base::AutoLock lock(any_thread_lock_); 675 base::AutoLock lock(any_thread_lock_);
666 if (any_thread().immediate_incoming_queue.empty()) 676 if (any_thread().immediate_incoming_queue.empty())
667 return true; 677 return true;
668 678
669 return any_thread().immediate_incoming_queue.front().enqueue_order() > 679 return any_thread().immediate_incoming_queue.front().enqueue_order() >
670 main_thread_only().current_fence; 680 main_thread_only().current_fence;
671 } 681 }
672 682
673 bool TaskQueueImpl::BlockedByFenceLocked() const { 683 bool TaskQueueImpl::BlockedByFenceLocked() const {
684 any_thread_lock_.AssertAcquired();
685
674 if (!main_thread_only().current_fence) 686 if (!main_thread_only().current_fence)
675 return false; 687 return false;
676 688
677 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 689 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
678 !main_thread_only().delayed_work_queue->BlockedByFence()) { 690 !main_thread_only().delayed_work_queue->BlockedByFence()) {
679 return false; 691 return false;
680 } 692 }
681 693
682 if (any_thread().immediate_incoming_queue.empty()) 694 if (any_thread().immediate_incoming_queue.empty())
683 return true; 695 return true;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter> 827 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter>
816 TaskQueueImpl::CreateQueueEnabledVoter() { 828 TaskQueueImpl::CreateQueueEnabledVoter() {
817 main_thread_only().voter_refcount++; 829 main_thread_only().voter_refcount++;
818 main_thread_only().is_enabled_refcount++; 830 main_thread_only().is_enabled_refcount++;
819 return base::MakeUnique<QueueEnabledVoterImpl>(this); 831 return base::MakeUnique<QueueEnabledVoterImpl>(this);
820 } 832 }
821 833
822 } // namespace internal 834 } // namespace internal
823 } // namespace scheduler 835 } // namespace scheduler
824 } // namespace blink 836 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698