| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |