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

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

Issue 2540663002: Add the concept of QueueEnabledVoters to blink scheduler TaskQueue (Closed)
Patch Set: Fix test crashes and address feedback. 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/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
9 #include "base/trace_event/blame_context.h" 10 #include "base/trace_event/blame_context.h"
10 #include "platform/scheduler/base/task_queue_manager.h" 11 #include "platform/scheduler/base/task_queue_manager.h"
11 #include "platform/scheduler/base/task_queue_manager_delegate.h" 12 #include "platform/scheduler/base/task_queue_manager_delegate.h"
12 #include "platform/scheduler/base/time_domain.h" 13 #include "platform/scheduler/base/time_domain.h"
13 #include "platform/scheduler/base/work_queue.h" 14 #include "platform/scheduler/base/work_queue.h"
14 15
15 namespace blink { 16 namespace blink {
16 namespace scheduler { 17 namespace scheduler {
17 18
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 150
150 TaskQueueImpl::MainThreadOnly::MainThreadOnly( 151 TaskQueueImpl::MainThreadOnly::MainThreadOnly(
151 TaskQueueManager* task_queue_manager, 152 TaskQueueManager* task_queue_manager,
152 TaskQueueImpl* task_queue, 153 TaskQueueImpl* task_queue,
153 TimeDomain* time_domain) 154 TimeDomain* time_domain)
154 : task_queue_manager(task_queue_manager), 155 : task_queue_manager(task_queue_manager),
155 time_domain(time_domain), 156 time_domain(time_domain),
156 delayed_work_queue(new WorkQueue(task_queue, "delayed")), 157 delayed_work_queue(new WorkQueue(task_queue, "delayed")),
157 immediate_work_queue(new WorkQueue(task_queue, "immediate")), 158 immediate_work_queue(new WorkQueue(task_queue, "immediate")),
158 set_index(0), 159 set_index(0),
159 is_enabled(true), 160 is_enabled_refcount(0),
161 voter_refcount(0),
160 blame_context(nullptr), 162 blame_context(nullptr),
161 current_fence(0) {} 163 current_fence(0) {}
162 164
163 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} 165 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
164 166
165 void TaskQueueImpl::UnregisterTaskQueue() { 167 void TaskQueueImpl::UnregisterTaskQueue() {
166 base::AutoLock lock(any_thread_lock_); 168 base::AutoLock lock(any_thread_lock_);
167 if (main_thread_only().time_domain) 169 if (main_thread_only().time_domain)
168 main_thread_only().time_domain->UnregisterQueue(this); 170 main_thread_only().time_domain->UnregisterQueue(this);
169 if (!any_thread().task_queue_manager) 171 if (!any_thread().task_queue_manager)
170 return; 172 return;
171 any_thread().time_domain = nullptr; 173 any_thread().time_domain = nullptr;
172 main_thread_only().time_domain = nullptr; 174 main_thread_only().time_domain = nullptr;
173 any_thread().task_queue_manager->UnregisterTaskQueue(this); 175 any_thread().task_queue_manager->UnregisterTaskQueue(this);
174 176
175 any_thread().task_queue_manager = nullptr; 177 any_thread().task_queue_manager = nullptr;
176 main_thread_only().task_queue_manager = nullptr; 178 main_thread_only().task_queue_manager = nullptr;
177 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); 179 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>();
178 any_thread().immediate_incoming_queue = std::queue<Task>(); 180 any_thread().immediate_incoming_queue = std::queue<Task>();
179 main_thread_only().immediate_work_queue.reset(); 181 main_thread_only().immediate_work_queue.reset();
180 main_thread_only().delayed_work_queue.reset(); 182 main_thread_only().delayed_work_queue.reset();
181 } 183 }
182 184
183 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { 185 bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
184 base::AutoLock lock(any_thread_lock_); 186 base::AutoLock lock(any_thread_lock_);
185 return base::PlatformThread::CurrentId() == thread_id_; 187 return base::PlatformThread::CurrentId() == thread_id_;
186 } 188 }
187 189
188
189 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, 190 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here,
190 const base::Closure& task, 191 const base::Closure& task,
191 base::TimeDelta delay) { 192 base::TimeDelta delay) {
192 if (delay.is_zero()) 193 if (delay.is_zero())
193 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); 194 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL);
194 195
195 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); 196 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL);
196 } 197 }
197 198
198 bool TaskQueueImpl::PostNonNestableDelayedTask( 199 bool TaskQueueImpl::PostNonNestableDelayedTask(
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 EnqueueOrder sequence_number, 326 EnqueueOrder sequence_number,
326 bool nestable) { 327 bool nestable) {
327 if (any_thread().immediate_incoming_queue.empty()) 328 if (any_thread().immediate_incoming_queue.empty())
328 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); 329 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
329 // 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
330 // it run. 331 // it run.
331 if (any_thread().immediate_incoming_queue.empty()) { 332 if (any_thread().immediate_incoming_queue.empty()) {
332 // There's no point posting a DoWork for a disabled queue, however we can 333 // There's no point posting a DoWork for a disabled queue, however we can
333 // only tell if it's disabled from the main thread. 334 // only tell if it's disabled from the main thread.
334 if (base::PlatformThread::CurrentId() == thread_id_) { 335 if (base::PlatformThread::CurrentId() == thread_id_) {
335 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) 336 if (IsQueueEnabled() && !BlockedByFenceLocked())
336 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 337 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
337 } else { 338 } else {
338 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 339 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
339 } 340 }
340 } 341 }
341 any_thread().immediate_incoming_queue.emplace( 342 any_thread().immediate_incoming_queue.emplace(
342 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); 343 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber);
343 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back()); 344 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back());
344 TraceQueueSize(true); 345 TraceQueueSize(true);
345 } 346 }
346 347
347 void TaskQueueImpl::SetQueueEnabled(bool enabled) {
348 if (main_thread_only().is_enabled == enabled)
349 return;
350 main_thread_only().is_enabled = enabled;
351 if (!main_thread_only().task_queue_manager)
352 return;
353 if (enabled) {
354 // Note it's the job of the selector to tell the TaskQueueManager if
355 // a DoWork needs posting.
356 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
357 } else {
358 main_thread_only().task_queue_manager->selector_.DisableQueue(this);
359 }
360 }
361
362 bool TaskQueueImpl::IsQueueEnabled() const {
363 return main_thread_only().is_enabled;
364 }
365
366 bool TaskQueueImpl::IsEmpty() const { 348 bool TaskQueueImpl::IsEmpty() const {
367 if (!main_thread_only().delayed_work_queue->Empty() || 349 if (!main_thread_only().delayed_work_queue->Empty() ||
368 !main_thread_only().delayed_incoming_queue.empty() || 350 !main_thread_only().delayed_incoming_queue.empty() ||
369 !main_thread_only().immediate_work_queue->Empty()) { 351 !main_thread_only().immediate_work_queue->Empty()) {
370 return false; 352 return false;
371 } 353 }
372 354
373 base::AutoLock lock(any_thread_lock_); 355 base::AutoLock lock(any_thread_lock_);
374 return any_thread().immediate_incoming_queue.empty(); 356 return any_thread().immediate_incoming_queue.empty();
375 } 357 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 } 481 }
500 482
501 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { 483 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const {
502 base::AutoLock lock(any_thread_lock_); 484 base::AutoLock lock(any_thread_lock_);
503 state->BeginDictionary(); 485 state->BeginDictionary();
504 state->SetString("name", GetName()); 486 state->SetString("name", GetName());
505 state->SetString( 487 state->SetString(
506 "task_queue_id", 488 "task_queue_id",
507 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( 489 base::StringPrintf("%" PRIx64, static_cast<uint64_t>(
508 reinterpret_cast<uintptr_t>(this)))); 490 reinterpret_cast<uintptr_t>(this))));
509 state->SetBoolean("enabled", main_thread_only().is_enabled); 491 state->SetBoolean("enabled", IsQueueEnabled());
510 state->SetString("time_domain_name", 492 state->SetString("time_domain_name",
511 main_thread_only().time_domain->GetName()); 493 main_thread_only().time_domain->GetName());
512 bool verbose_tracing_enabled = false; 494 bool verbose_tracing_enabled = false;
513 TRACE_EVENT_CATEGORY_GROUP_ENABLED( 495 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
514 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); 496 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled);
515 state->SetInteger("immediate_incoming_queue_size", 497 state->SetInteger("immediate_incoming_queue_size",
516 any_thread().immediate_incoming_queue.size()); 498 any_thread().immediate_incoming_queue.size());
517 state->SetInteger("delayed_incoming_queue_size", 499 state->SetInteger("delayed_incoming_queue_size",
518 main_thread_only().delayed_incoming_queue.size()); 500 main_thread_only().delayed_incoming_queue.size());
519 state->SetInteger("immediate_work_queue_size", 501 state->SetInteger("immediate_work_queue_size",
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 base::AutoLock lock(any_thread_lock_); 615 base::AutoLock lock(any_thread_lock_);
634 if (!any_thread().immediate_incoming_queue.empty() && 616 if (!any_thread().immediate_incoming_queue.empty() &&
635 any_thread().immediate_incoming_queue.front().enqueue_order() > 617 any_thread().immediate_incoming_queue.front().enqueue_order() >
636 previous_fence && 618 previous_fence &&
637 any_thread().immediate_incoming_queue.front().enqueue_order() < 619 any_thread().immediate_incoming_queue.front().enqueue_order() <
638 main_thread_only().current_fence) { 620 main_thread_only().current_fence) {
639 task_unblocked = true; 621 task_unblocked = true;
640 } 622 }
641 } 623 }
642 624
643 if (main_thread_only().is_enabled && task_unblocked) { 625 if (IsQueueEnabled() && task_unblocked) {
644 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 626 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
645 FROM_HERE); 627 FROM_HERE);
646 } 628 }
647 } 629 }
648 630
649 void TaskQueueImpl::RemoveFence() { 631 void TaskQueueImpl::RemoveFence() {
650 if (!main_thread_only().task_queue_manager) 632 if (!main_thread_only().task_queue_manager)
651 return; 633 return;
652 634
653 EnqueueOrder previous_fence = main_thread_only().current_fence; 635 EnqueueOrder previous_fence = main_thread_only().current_fence;
654 main_thread_only().current_fence = 0; 636 main_thread_only().current_fence = 0;
655 637
656 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); 638 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence();
657 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); 639 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence();
658 640
659 if (!task_unblocked && previous_fence) { 641 if (!task_unblocked && previous_fence) {
660 base::AutoLock lock(any_thread_lock_); 642 base::AutoLock lock(any_thread_lock_);
661 if (!any_thread().immediate_incoming_queue.empty() && 643 if (!any_thread().immediate_incoming_queue.empty() &&
662 any_thread().immediate_incoming_queue.front().enqueue_order() > 644 any_thread().immediate_incoming_queue.front().enqueue_order() >
663 previous_fence) { 645 previous_fence) {
664 task_unblocked = true; 646 task_unblocked = true;
665 } 647 }
666 } 648 }
667 649
668 if (main_thread_only().is_enabled && task_unblocked) { 650 if (IsQueueEnabled() && task_unblocked) {
669 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 651 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
670 FROM_HERE); 652 FROM_HERE);
671 } 653 }
672 } 654 }
673 655
674 bool TaskQueueImpl::BlockedByFence() const { 656 bool TaskQueueImpl::BlockedByFence() const {
675 if (!main_thread_only().current_fence) 657 if (!main_thread_only().current_fence)
676 return false; 658 return false;
677 659
678 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 660 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 state->SetInteger("sequence_num", task.sequence_num); 735 state->SetInteger("sequence_num", task.sequence_num);
754 state->SetBoolean("nestable", task.nestable); 736 state->SetBoolean("nestable", task.nestable);
755 state->SetBoolean("is_high_res", task.is_high_res); 737 state->SetBoolean("is_high_res", task.is_high_res);
756 state->SetBoolean("is_cancelled", task.task.IsCancelled()); 738 state->SetBoolean("is_cancelled", task.task.IsCancelled());
757 state->SetDouble( 739 state->SetDouble(
758 "delayed_run_time", 740 "delayed_run_time",
759 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); 741 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
760 state->EndDictionary(); 742 state->EndDictionary();
761 } 743 }
762 744
745 TaskQueueImpl::QueueEnabledVoterImpl::QueueEnabledVoterImpl(
746 TaskQueueImpl* task_queue)
747 : task_queue_(task_queue), enabled_(true) {}
748
749 TaskQueueImpl::QueueEnabledVoterImpl::~QueueEnabledVoterImpl() {
750 task_queue_->RemoveQueueEnabledVoter(this);
751 }
752
753 void TaskQueueImpl::QueueEnabledVoterImpl::SetQueueEnabled(bool enabled) {
754 if (enabled_ == enabled)
755 return;
756
757 task_queue_->OnQueueEnabledVoteChanged(enabled);
758 enabled_ = enabled;
759 }
760
761 void TaskQueueImpl::RemoveQueueEnabledVoter(
762 const QueueEnabledVoterImpl* voter) {
763 // Bail out if we're being called from TaskQueueImpl::UnregisterTaskQueue.
764 if (!main_thread_only().time_domain)
765 return;
766
767 bool was_enabled = IsQueueEnabled();
768 if (voter->enabled_) {
769 main_thread_only().is_enabled_refcount--;
770 DCHECK_GE(main_thread_only().is_enabled_refcount, 0);
771 }
772
773 main_thread_only().voter_refcount--;
774 DCHECK_GE(main_thread_only().voter_refcount, 0);
775
776 bool is_enabled = IsQueueEnabled();
777 if (was_enabled != is_enabled)
778 EnableOrDisableWithSelector(is_enabled);
779 }
780
781 bool TaskQueueImpl::IsQueueEnabled() const {
782 return main_thread_only().is_enabled_refcount ==
783 main_thread_only().voter_refcount;
784 }
785
786 void TaskQueueImpl::OnQueueEnabledVoteChanged(bool enabled) {
787 bool was_enabled = IsQueueEnabled();
788 if (enabled) {
789 main_thread_only().is_enabled_refcount++;
790 DCHECK_LE(main_thread_only().is_enabled_refcount,
791 main_thread_only().voter_refcount);
792 } else {
793 main_thread_only().is_enabled_refcount--;
794 DCHECK_GE(main_thread_only().is_enabled_refcount, 0);
795 }
796
797 bool is_enabled = IsQueueEnabled();
798 if (was_enabled != is_enabled)
799 EnableOrDisableWithSelector(is_enabled);
800 }
801
802 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) {
803 if (!main_thread_only().task_queue_manager)
804 return;
805
806 if (enable) {
807 // Note it's the job of the selector to tell the TaskQueueManager if
808 // a DoWork needs posting.
809 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
810 } else {
811 main_thread_only().task_queue_manager->selector_.DisableQueue(this);
812 }
813 }
814
815 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter>
816 TaskQueueImpl::CreateQueueEnabledVoter() {
817 main_thread_only().voter_refcount++;
818 main_thread_only().is_enabled_refcount++;
819 return base::MakeUnique<QueueEnabledVoterImpl>(this);
820 }
821
763 } // namespace internal 822 } // namespace internal
764 } // namespace scheduler 823 } // namespace scheduler
765 } // namespace blink 824 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698