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