| 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/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 Loading... |
| 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_); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 TraceQueueSize(false); | 322 TraceQueueSize(false); |
| 320 } | 323 } |
| 321 | 324 |
| 322 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( | 325 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( |
| 323 const tracked_objects::Location& posted_from, | 326 const tracked_objects::Location& posted_from, |
| 324 const base::Closure& task, | 327 const base::Closure& task, |
| 325 base::TimeTicks desired_run_time, | 328 base::TimeTicks desired_run_time, |
| 326 EnqueueOrder sequence_number, | 329 EnqueueOrder sequence_number, |
| 327 bool nestable) { | 330 bool nestable) { |
| 328 if (any_thread().immediate_incoming_queue.empty()) | 331 if (any_thread().immediate_incoming_queue.empty()) |
| 329 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 332 any_thread().time_domain->OnQueueHasIncomingImmediateWork(this); |
| 330 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make | 333 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 331 // it run. | 334 // it run. |
| 332 if (any_thread().immediate_incoming_queue.empty()) { | 335 if (any_thread().immediate_incoming_queue.empty()) { |
| 333 // There's no point posting a DoWork for a disabled queue, however we can | 336 // There's no point posting a DoWork for a disabled queue, however we can |
| 334 // only tell if it's disabled from the main thread. | 337 // only tell if it's disabled from the main thread. |
| 335 if (base::PlatformThread::CurrentId() == thread_id_) { | 338 if (base::PlatformThread::CurrentId() == thread_id_) { |
| 336 if (IsQueueEnabled() && !BlockedByFenceLocked()) | 339 if (IsQueueEnabled() && !BlockedByFenceLocked()) |
| 337 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 340 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 338 } else { | 341 } else { |
| 339 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 342 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 340 } | 343 } |
| 341 } | 344 } |
| 342 any_thread().immediate_incoming_queue.emplace_back( | 345 any_thread().immediate_incoming_queue.emplace_back( |
| 343 posted_from, task, desired_run_time, sequence_number, nestable, | 346 posted_from, task, desired_run_time, sequence_number, nestable, |
| 344 sequence_number); | 347 sequence_number); |
| 345 any_thread().task_queue_manager->DidQueueTask( | 348 any_thread().task_queue_manager->DidQueueTask( |
| 346 any_thread().immediate_incoming_queue.back()); | 349 any_thread().immediate_incoming_queue.back()); |
| 347 TraceQueueSize(true); | 350 TraceQueueSize(true); |
| 348 } | 351 } |
| 349 | 352 |
| 353 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { |
| 354 if (!main_thread_only().immediate_work_queue->Empty()) |
| 355 return; |
| 356 |
| 357 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); |
| 358 } |
| 359 |
| 360 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { |
| 361 base::AutoLock lock(any_thread_lock_); |
| 362 WTF::Deque<TaskQueueImpl::Task> queue; |
| 363 queue.swap(any_thread().immediate_incoming_queue); |
| 364 return queue; |
| 365 } |
| 366 |
| 350 bool TaskQueueImpl::IsEmpty() const { | 367 bool TaskQueueImpl::IsEmpty() const { |
| 351 if (!main_thread_only().delayed_work_queue->Empty() || | 368 if (!main_thread_only().delayed_work_queue->Empty() || |
| 352 !main_thread_only().delayed_incoming_queue.empty() || | 369 !main_thread_only().delayed_incoming_queue.empty() || |
| 353 !main_thread_only().immediate_work_queue->Empty()) { | 370 !main_thread_only().immediate_work_queue->Empty()) { |
| 354 return false; | 371 return false; |
| 355 } | 372 } |
| 356 | 373 |
| 357 base::AutoLock lock(any_thread_lock_); | 374 base::AutoLock lock(any_thread_lock_); |
| 358 return any_thread().immediate_incoming_queue.empty(); | 375 return any_thread().immediate_incoming_queue.empty(); |
| 359 } | 376 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 } | 432 } |
| 416 | 433 |
| 417 // Make sure the next wake up is scheduled. | 434 // Make sure the next wake up is scheduled. |
| 418 if (!main_thread_only().delayed_incoming_queue.empty()) { | 435 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 419 main_thread_only().time_domain->ScheduleDelayedWork( | 436 main_thread_only().time_domain->ScheduleDelayedWork( |
| 420 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 437 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 421 lazy_now->Now()); | 438 lazy_now->Now()); |
| 422 } | 439 } |
| 423 } | 440 } |
| 424 | 441 |
| 425 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { | |
| 426 if (!main_thread_only().task_queue_manager) | |
| 427 return false; | |
| 428 | |
| 429 if (!main_thread_only().immediate_work_queue->Empty()) | |
| 430 return true; | |
| 431 | |
| 432 base::AutoLock lock(any_thread_lock_); | |
| 433 main_thread_only().immediate_work_queue->SwapLocked( | |
| 434 any_thread().immediate_incoming_queue); | |
| 435 // |immediate_work_queue| is now empty so updates are no longer required. | |
| 436 return false; | |
| 437 } | |
| 438 | |
| 439 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { | 442 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { |
| 440 bool is_tracing; | 443 bool is_tracing; |
| 441 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, | 444 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, |
| 442 &is_tracing); | 445 &is_tracing); |
| 443 if (!is_tracing) | 446 if (!is_tracing) |
| 444 return; | 447 return; |
| 445 | 448 |
| 446 // It's only safe to access the work queues from the main thread. | 449 // It's only safe to access the work queues from the main thread. |
| 447 // TODO(alexclarke): We should find another way of tracing this | 450 // TODO(alexclarke): We should find another way of tracing this |
| 448 if (base::PlatformThread::CurrentId() != thread_id_) | 451 if (base::PlatformThread::CurrentId() != thread_id_) |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 DCHECK(any_thread().time_domain); | 573 DCHECK(any_thread().time_domain); |
| 571 if (!any_thread().time_domain) | 574 if (!any_thread().time_domain) |
| 572 return; | 575 return; |
| 573 DCHECK(main_thread_checker_.CalledOnValidThread()); | 576 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 574 if (time_domain == main_thread_only().time_domain) | 577 if (time_domain == main_thread_only().time_domain) |
| 575 return; | 578 return; |
| 576 | 579 |
| 577 any_thread().time_domain = time_domain; | 580 any_thread().time_domain = time_domain; |
| 578 } | 581 } |
| 579 // We rely here on TimeDomain::MigrateQueue being thread-safe to use with | 582 // We rely here on TimeDomain::MigrateQueue being thread-safe to use with |
| 580 // TimeDomain::Register/UnregisterAsUpdatableTaskQueue. | 583 // TimeDomain::Register. |
| 581 main_thread_only().time_domain->MigrateQueue(this, time_domain); | 584 main_thread_only().time_domain->MigrateQueue(this, time_domain); |
| 582 main_thread_only().time_domain = time_domain; | 585 main_thread_only().time_domain = time_domain; |
| 583 } | 586 } |
| 584 | 587 |
| 585 TimeDomain* TaskQueueImpl::GetTimeDomain() const { | 588 TimeDomain* TaskQueueImpl::GetTimeDomain() const { |
| 586 if (base::PlatformThread::CurrentId() == thread_id_) | 589 if (base::PlatformThread::CurrentId() == thread_id_) |
| 587 return main_thread_only().time_domain; | 590 return main_thread_only().time_domain; |
| 588 | 591 |
| 589 base::AutoLock lock(any_thread_lock_); | 592 base::AutoLock lock(any_thread_lock_); |
| 590 return any_thread().time_domain; | 593 return any_thread().time_domain; |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 bool is_enabled = IsQueueEnabled(); | 795 bool is_enabled = IsQueueEnabled(); |
| 793 if (was_enabled != is_enabled) | 796 if (was_enabled != is_enabled) |
| 794 EnableOrDisableWithSelector(is_enabled); | 797 EnableOrDisableWithSelector(is_enabled); |
| 795 } | 798 } |
| 796 | 799 |
| 797 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { | 800 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { |
| 798 if (!main_thread_only().task_queue_manager) | 801 if (!main_thread_only().task_queue_manager) |
| 799 return; | 802 return; |
| 800 | 803 |
| 801 if (enable) { | 804 if (enable) { |
| 802 // Note it's the job of the selector to tell the TaskQueueManager if | 805 // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts |
| 803 // a DoWork needs posting. | 806 // a DoWork if needed. |
| 804 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 807 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
| 805 } else { | 808 } else { |
| 806 main_thread_only().task_queue_manager->selector_.DisableQueue(this); | 809 main_thread_only().task_queue_manager->selector_.DisableQueue(this); |
| 807 } | 810 } |
| 808 } | 811 } |
| 809 | 812 |
| 810 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter> | 813 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter> |
| 811 TaskQueueImpl::CreateQueueEnabledVoter() { | 814 TaskQueueImpl::CreateQueueEnabledVoter() { |
| 812 main_thread_only().voter_refcount++; | 815 main_thread_only().voter_refcount++; |
| 813 main_thread_only().is_enabled_refcount++; | 816 main_thread_only().is_enabled_refcount++; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 829 main_thread_only().delayed_incoming_queue.top().delayed_run_time == | 832 main_thread_only().delayed_incoming_queue.top().delayed_run_time == |
| 830 first_task_runtime) { | 833 first_task_runtime) { |
| 831 remaining_tasks.push(std::move( | 834 remaining_tasks.push(std::move( |
| 832 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()))); | 835 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()))); |
| 833 } | 836 } |
| 834 main_thread_only().delayed_incoming_queue.pop(); | 837 main_thread_only().delayed_incoming_queue.pop(); |
| 835 } | 838 } |
| 836 main_thread_only().delayed_incoming_queue = std::move(remaining_tasks); | 839 main_thread_only().delayed_incoming_queue = std::move(remaining_tasks); |
| 837 } | 840 } |
| 838 | 841 |
| 842 void TaskQueueImpl::PushImmediateIncomingTaskForTest( |
| 843 TaskQueueImpl::Task&& task) { |
| 844 base::AutoLock lock(any_thread_lock_); |
| 845 any_thread().immediate_incoming_queue.push_back(std::move(task)); |
| 846 } |
| 847 |
| 839 } // namespace internal | 848 } // namespace internal |
| 840 } // namespace scheduler | 849 } // namespace scheduler |
| 841 } // namespace blink | 850 } // namespace blink |
| OLD | NEW |