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

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: Few tweaks 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 any_thread().task_queue_manager->OnQueueHasImmediateWork(this);
334 // only tell if it's disabled from the main thread. 334 any_thread().time_domain->OnQueueHasImmediateWork(this);
335 if (base::PlatformThread::CurrentId() == thread_id_) {
336 if (IsQueueEnabled() && !BlockedByFenceLocked())
337 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
338 } else {
339 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
340 }
341 } 335 }
336
342 any_thread().immediate_incoming_queue.emplace( 337 any_thread().immediate_incoming_queue.emplace(
343 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); 338 posted_from, task, desired_run_time, sequence_number, nestable,
344 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back()); 339 sequence_number);
340 any_thread().task_queue_manager->DidQueueTask(
341 any_thread().immediate_incoming_queue.back());
345 TraceQueueSize(true); 342 TraceQueueSize(true);
346 } 343 }
347 344
345 void TaskQueueImpl::OnIncomingImmediateTaskAvailable() {
Sami 2016/12/05 17:52:54 I think having this method makes sense but the nam
alex clarke (OOO till 29th) 2016/12/06 17:37:54 Done.
346 // Note a call to OnImmediateWorkQueueHasBecomeEmpty could have got here first
347 // so there may not actually be any work to do.
348 if (!main_thread_only().immediate_work_queue->Empty())
349 return;
350
351 base::AutoLock lock(any_thread_lock_);
352 if (any_thread().immediate_incoming_queue.empty())
353 return;
354
355 main_thread_only().immediate_work_queue->SwapLocked(
356 any_thread().immediate_incoming_queue);
357 }
358
359 void TaskQueueImpl::OnImmediateWorkQueueHasBecomeEmpty(
360 std::queue<TaskQueueImpl::Task>* work_queue) {
361 base::AutoLock lock(any_thread_lock_);
362 DCHECK(work_queue->empty());
363
364 if (any_thread().immediate_incoming_queue.empty())
365 return;
366
367 std::swap(any_thread().immediate_incoming_queue, *work_queue);
368 }
369
348 bool TaskQueueImpl::IsEmpty() const { 370 bool TaskQueueImpl::IsEmpty() const {
349 if (!main_thread_only().delayed_work_queue->Empty() || 371 if (!main_thread_only().delayed_work_queue->Empty() ||
350 !main_thread_only().delayed_incoming_queue.empty() || 372 !main_thread_only().delayed_incoming_queue.empty() ||
351 !main_thread_only().immediate_work_queue->Empty()) { 373 !main_thread_only().immediate_work_queue->Empty()) {
352 return false; 374 return false;
353 } 375 }
354 376
355 base::AutoLock lock(any_thread_lock_); 377 base::AutoLock lock(any_thread_lock_);
356 return any_thread().immediate_incoming_queue.empty(); 378 return any_thread().immediate_incoming_queue.empty();
357 } 379 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 } 435 }
414 436
415 // Make sure the next wake up is scheduled. 437 // Make sure the next wake up is scheduled.
416 if (!main_thread_only().delayed_incoming_queue.empty()) { 438 if (!main_thread_only().delayed_incoming_queue.empty()) {
417 main_thread_only().time_domain->ScheduleDelayedWork( 439 main_thread_only().time_domain->ScheduleDelayedWork(
418 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, 440 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time,
419 lazy_now->Now()); 441 lazy_now->Now());
420 } 442 }
421 } 443 }
422 444
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 { 445 void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
438 bool is_tracing; 446 bool is_tracing;
439 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, 447 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
440 &is_tracing); 448 &is_tracing);
441 if (!is_tracing) 449 if (!is_tracing)
442 return; 450 return;
443 451
444 // It's only safe to access the work queues from the main thread. 452 // It's only safe to access the work queues from the main thread.
445 // TODO(alexclarke): We should find another way of tracing this 453 // TODO(alexclarke): We should find another way of tracing this
446 if (base::PlatformThread::CurrentId() != thread_id_) 454 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. 575 // another way of asserting that UnregisterTaskQueue has not been called.
568 DCHECK(any_thread().time_domain); 576 DCHECK(any_thread().time_domain);
569 if (!any_thread().time_domain) 577 if (!any_thread().time_domain)
570 return; 578 return;
571 DCHECK(main_thread_checker_.CalledOnValidThread()); 579 DCHECK(main_thread_checker_.CalledOnValidThread());
572 if (time_domain == main_thread_only().time_domain) 580 if (time_domain == main_thread_only().time_domain)
573 return; 581 return;
574 582
575 any_thread().time_domain = time_domain; 583 any_thread().time_domain = time_domain;
576 } 584 }
577 // We rely here on TimeDomain::MigrateQueue being thread-safe to use with 585
578 // TimeDomain::Register/UnregisterAsUpdatableTaskQueue.
579 main_thread_only().time_domain->MigrateQueue(this, time_domain); 586 main_thread_only().time_domain->MigrateQueue(this, time_domain);
580 main_thread_only().time_domain = time_domain; 587 main_thread_only().time_domain = time_domain;
581 } 588 }
582 589
583 TimeDomain* TaskQueueImpl::GetTimeDomain() const { 590 TimeDomain* TaskQueueImpl::GetTimeDomain() const {
584 if (base::PlatformThread::CurrentId() == thread_id_) 591 if (base::PlatformThread::CurrentId() == thread_id_)
585 return main_thread_only().time_domain; 592 return main_thread_only().time_domain;
586 593
587 base::AutoLock lock(any_thread_lock_); 594 base::AutoLock lock(any_thread_lock_);
588 return any_thread().time_domain; 595 return any_thread().time_domain;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 671
665 base::AutoLock lock(any_thread_lock_); 672 base::AutoLock lock(any_thread_lock_);
666 if (any_thread().immediate_incoming_queue.empty()) 673 if (any_thread().immediate_incoming_queue.empty())
667 return true; 674 return true;
668 675
669 return any_thread().immediate_incoming_queue.front().enqueue_order() > 676 return any_thread().immediate_incoming_queue.front().enqueue_order() >
670 main_thread_only().current_fence; 677 main_thread_only().current_fence;
671 } 678 }
672 679
673 bool TaskQueueImpl::BlockedByFenceLocked() const { 680 bool TaskQueueImpl::BlockedByFenceLocked() const {
681 any_thread_lock_.AssertAcquired();
682
674 if (!main_thread_only().current_fence) 683 if (!main_thread_only().current_fence)
675 return false; 684 return false;
676 685
677 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 686 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
678 !main_thread_only().delayed_work_queue->BlockedByFence()) { 687 !main_thread_only().delayed_work_queue->BlockedByFence()) {
679 return false; 688 return false;
680 } 689 }
681 690
682 if (any_thread().immediate_incoming_queue.empty()) 691 if (any_thread().immediate_incoming_queue.empty())
683 return true; 692 return true;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter> 824 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter>
816 TaskQueueImpl::CreateQueueEnabledVoter() { 825 TaskQueueImpl::CreateQueueEnabledVoter() {
817 main_thread_only().voter_refcount++; 826 main_thread_only().voter_refcount++;
818 main_thread_only().is_enabled_refcount++; 827 main_thread_only().is_enabled_refcount++;
819 return base::MakeUnique<QueueEnabledVoterImpl>(this); 828 return base::MakeUnique<QueueEnabledVoterImpl>(this);
820 } 829 }
821 830
822 } // namespace internal 831 } // namespace internal
823 } // namespace scheduler 832 } // namespace scheduler
824 } // namespace blink 833 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698