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

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: Added a couple of extra tests 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)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 EnqueueOrder sequence_number, 327 EnqueueOrder sequence_number,
326 bool nestable) { 328 bool nestable) {
327 if (any_thread().immediate_incoming_queue.empty()) 329 if (any_thread().immediate_incoming_queue.empty())
328 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); 330 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
329 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make 331 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
330 // it run. 332 // it run.
331 if (any_thread().immediate_incoming_queue.empty()) { 333 if (any_thread().immediate_incoming_queue.empty()) {
332 // There's no point posting a DoWork for a disabled queue, however we can 334 // 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. 335 // only tell if it's disabled from the main thread.
334 if (base::PlatformThread::CurrentId() == thread_id_) { 336 if (base::PlatformThread::CurrentId() == thread_id_) {
335 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) 337 if (IsQueueEnabled() && !BlockedByFenceLocked())
336 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 338 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
337 } else { 339 } else {
338 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 340 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
339 } 341 }
340 } 342 }
341 any_thread().immediate_incoming_queue.emplace( 343 any_thread().immediate_incoming_queue.emplace(
342 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); 344 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()); 345 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back());
344 TraceQueueSize(true); 346 TraceQueueSize(true);
345 } 347 }
346 348
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 { 349 bool TaskQueueImpl::IsEmpty() const {
367 if (!main_thread_only().delayed_work_queue->Empty() || 350 if (!main_thread_only().delayed_work_queue->Empty() ||
368 !main_thread_only().delayed_incoming_queue.empty() || 351 !main_thread_only().delayed_incoming_queue.empty() ||
369 !main_thread_only().immediate_work_queue->Empty()) { 352 !main_thread_only().immediate_work_queue->Empty()) {
370 return false; 353 return false;
371 } 354 }
372 355
373 base::AutoLock lock(any_thread_lock_); 356 base::AutoLock lock(any_thread_lock_);
374 return any_thread().immediate_incoming_queue.empty(); 357 return any_thread().immediate_incoming_queue.empty();
375 } 358 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 } 482 }
500 483
501 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { 484 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const {
502 base::AutoLock lock(any_thread_lock_); 485 base::AutoLock lock(any_thread_lock_);
503 state->BeginDictionary(); 486 state->BeginDictionary();
504 state->SetString("name", GetName()); 487 state->SetString("name", GetName());
505 state->SetString( 488 state->SetString(
506 "task_queue_id", 489 "task_queue_id",
507 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( 490 base::StringPrintf("%" PRIx64, static_cast<uint64_t>(
508 reinterpret_cast<uintptr_t>(this)))); 491 reinterpret_cast<uintptr_t>(this))));
509 state->SetBoolean("enabled", main_thread_only().is_enabled); 492 state->SetBoolean("enabled", IsQueueEnabled());
510 state->SetString("time_domain_name", 493 state->SetString("time_domain_name",
511 main_thread_only().time_domain->GetName()); 494 main_thread_only().time_domain->GetName());
512 bool verbose_tracing_enabled = false; 495 bool verbose_tracing_enabled = false;
513 TRACE_EVENT_CATEGORY_GROUP_ENABLED( 496 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
514 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); 497 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled);
515 state->SetInteger("immediate_incoming_queue_size", 498 state->SetInteger("immediate_incoming_queue_size",
516 any_thread().immediate_incoming_queue.size()); 499 any_thread().immediate_incoming_queue.size());
517 state->SetInteger("delayed_incoming_queue_size", 500 state->SetInteger("delayed_incoming_queue_size",
518 main_thread_only().delayed_incoming_queue.size()); 501 main_thread_only().delayed_incoming_queue.size());
519 state->SetInteger("immediate_work_queue_size", 502 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_); 616 base::AutoLock lock(any_thread_lock_);
634 if (!any_thread().immediate_incoming_queue.empty() && 617 if (!any_thread().immediate_incoming_queue.empty() &&
635 any_thread().immediate_incoming_queue.front().enqueue_order() > 618 any_thread().immediate_incoming_queue.front().enqueue_order() >
636 previous_fence && 619 previous_fence &&
637 any_thread().immediate_incoming_queue.front().enqueue_order() < 620 any_thread().immediate_incoming_queue.front().enqueue_order() <
638 main_thread_only().current_fence) { 621 main_thread_only().current_fence) {
639 task_unblocked = true; 622 task_unblocked = true;
640 } 623 }
641 } 624 }
642 625
643 if (main_thread_only().is_enabled && task_unblocked) { 626 if (IsQueueEnabled() && task_unblocked) {
644 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 627 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
645 FROM_HERE); 628 FROM_HERE);
646 } 629 }
647 } 630 }
648 631
649 void TaskQueueImpl::RemoveFence() { 632 void TaskQueueImpl::RemoveFence() {
650 if (!main_thread_only().task_queue_manager) 633 if (!main_thread_only().task_queue_manager)
651 return; 634 return;
652 635
653 EnqueueOrder previous_fence = main_thread_only().current_fence; 636 EnqueueOrder previous_fence = main_thread_only().current_fence;
654 main_thread_only().current_fence = 0; 637 main_thread_only().current_fence = 0;
655 638
656 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); 639 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence();
657 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); 640 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence();
658 641
659 if (!task_unblocked && previous_fence) { 642 if (!task_unblocked && previous_fence) {
660 base::AutoLock lock(any_thread_lock_); 643 base::AutoLock lock(any_thread_lock_);
661 if (!any_thread().immediate_incoming_queue.empty() && 644 if (!any_thread().immediate_incoming_queue.empty() &&
662 any_thread().immediate_incoming_queue.front().enqueue_order() > 645 any_thread().immediate_incoming_queue.front().enqueue_order() >
663 previous_fence) { 646 previous_fence) {
664 task_unblocked = true; 647 task_unblocked = true;
665 } 648 }
666 } 649 }
667 650
668 if (main_thread_only().is_enabled && task_unblocked) { 651 if (IsQueueEnabled() && task_unblocked) {
669 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 652 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
670 FROM_HERE); 653 FROM_HERE);
671 } 654 }
672 } 655 }
673 656
674 bool TaskQueueImpl::BlockedByFence() const { 657 bool TaskQueueImpl::BlockedByFence() const {
675 if (!main_thread_only().current_fence) 658 if (!main_thread_only().current_fence)
676 return false; 659 return false;
677 660
678 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 661 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); 736 state->SetInteger("sequence_num", task.sequence_num);
754 state->SetBoolean("nestable", task.nestable); 737 state->SetBoolean("nestable", task.nestable);
755 state->SetBoolean("is_high_res", task.is_high_res); 738 state->SetBoolean("is_high_res", task.is_high_res);
756 state->SetBoolean("is_cancelled", task.task.IsCancelled()); 739 state->SetBoolean("is_cancelled", task.task.IsCancelled());
757 state->SetDouble( 740 state->SetDouble(
758 "delayed_run_time", 741 "delayed_run_time",
759 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); 742 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
760 state->EndDictionary(); 743 state->EndDictionary();
761 } 744 }
762 745
746 TaskQueueImpl::QueueEnabledVoterImpl::QueueEnabledVoterImpl(
747 TaskQueueImpl* task_queue)
748 : task_queue_(task_queue), enabled_(true) {}
749
750 TaskQueueImpl::QueueEnabledVoterImpl::~QueueEnabledVoterImpl() {
751 task_queue_->RemoveQueueEnabledVoter(this);
752 }
753
754 TaskQueue* TaskQueueImpl::QueueEnabledVoterImpl::GetTaskQueue() const {
755 return task_queue_.get();
756 }
757
758 void TaskQueueImpl::QueueEnabledVoterImpl::SetQueueEnabled(bool enabled) {
759 if (enabled_ == enabled)
760 return;
761
762 task_queue_->QueueEnabledVoteChanged(enabled);
763 enabled_ = enabled;
764 }
765
766 void TaskQueueImpl::RemoveQueueEnabledVoter(
767 const QueueEnabledVoterImpl* voter) {
768 bool was_enabled = IsQueueEnabled();
769 if (voter->enabled_) {
770 main_thread_only().is_enabled_refcount--;
771 DCHECK_GE(main_thread_only().is_enabled_refcount, 0);
772 }
773
774 main_thread_only().voter_refcount--;
775 DCHECK_GE(main_thread_only().voter_refcount, 0);
776
777 bool is_enabled = IsQueueEnabled();
778 if (was_enabled != is_enabled)
779 EnableOrDisableWithSelector(is_enabled);
780 }
781
782 bool TaskQueueImpl::IsQueueEnabled() const {
783 return main_thread_only().is_enabled_refcount ==
784 main_thread_only().voter_refcount;
785 }
786
787 void TaskQueueImpl::QueueEnabledVoteChanged(bool enabled) {
788 bool was_enabled = IsQueueEnabled();
789 if (enabled) {
790 main_thread_only().is_enabled_refcount++;
791 DCHECK_LE(main_thread_only().is_enabled_refcount,
792 main_thread_only().voter_refcount);
793 } else {
794 main_thread_only().is_enabled_refcount--;
795 DCHECK_GE(main_thread_only().is_enabled_refcount, 0);
796 }
797
798 bool is_enabled = IsQueueEnabled();
799 if (was_enabled != is_enabled)
800 EnableOrDisableWithSelector(is_enabled);
801 }
802
803 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) {
804 if (!main_thread_only().task_queue_manager)
805 return;
806
807 if (enable) {
808 // Note it's the job of the selector to tell the TaskQueueManager if
809 // a DoWork needs posting.
810 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
811 } else {
812 main_thread_only().task_queue_manager->selector_.DisableQueue(this);
813 }
814 }
815
816 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter>
817 TaskQueueImpl::GetQueueEnabledVoter() {
818 main_thread_only().voter_refcount++;
819 main_thread_only().is_enabled_refcount++;
820 return base::MakeUnique<QueueEnabledVoterImpl>(this);
821 }
822
763 } // namespace internal 823 } // namespace internal
764 } // namespace scheduler 824 } // namespace scheduler
765 } // namespace blink 825 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698