| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "base/task_scheduler/scheduler_worker_pool_impl.h" | 5 #include "base/task_scheduler/scheduler_worker_pool_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 std::unique_ptr<SchedulerWorkerPoolImpl> SchedulerWorkerPoolImpl::Create( | 306 std::unique_ptr<SchedulerWorkerPoolImpl> SchedulerWorkerPoolImpl::Create( |
| 307 const SchedulerWorkerPoolParams& params, | 307 const SchedulerWorkerPoolParams& params, |
| 308 const ReEnqueueSequenceCallback& re_enqueue_sequence_callback, | 308 const ReEnqueueSequenceCallback& re_enqueue_sequence_callback, |
| 309 TaskTracker* task_tracker, | 309 TaskTracker* task_tracker, |
| 310 DelayedTaskManager* delayed_task_manager) { | 310 DelayedTaskManager* delayed_task_manager) { |
| 311 std::unique_ptr<SchedulerWorkerPoolImpl> worker_pool( | 311 std::unique_ptr<SchedulerWorkerPoolImpl> worker_pool( |
| 312 new SchedulerWorkerPoolImpl(params.name(), | 312 new SchedulerWorkerPoolImpl(params.name(), |
| 313 params.io_restriction(), | 313 params.io_restriction(), |
| 314 params.suggested_reclaim_time(), | 314 params.suggested_reclaim_time(), |
| 315 task_tracker, delayed_task_manager)); | 315 task_tracker, delayed_task_manager)); |
| 316 if (worker_pool->Initialize(params.priority_hint(), params.max_threads(), | 316 if (worker_pool->Initialize( |
| 317 re_enqueue_sequence_callback)) { | 317 params.priority_hint(), params.standby_thread_policy(), |
| 318 params.max_threads(), re_enqueue_sequence_callback)) { |
| 318 return worker_pool; | 319 return worker_pool; |
| 319 } | 320 } |
| 320 return nullptr; | 321 return nullptr; |
| 321 } | 322 } |
| 322 | 323 |
| 323 scoped_refptr<TaskRunner> SchedulerWorkerPoolImpl::CreateTaskRunnerWithTraits( | 324 scoped_refptr<TaskRunner> SchedulerWorkerPoolImpl::CreateTaskRunnerWithTraits( |
| 324 const TaskTraits& traits) { | 325 const TaskTraits& traits) { |
| 325 return make_scoped_refptr(new SchedulerParallelTaskRunner(traits, this)); | 326 return make_scoped_refptr(new SchedulerParallelTaskRunner(traits, this)); |
| 326 } | 327 } |
| 327 | 328 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 worker->JoinForTesting(); | 446 worker->JoinForTesting(); |
| 446 | 447 |
| 447 DCHECK(!join_for_testing_returned_.IsSignaled()); | 448 DCHECK(!join_for_testing_returned_.IsSignaled()); |
| 448 join_for_testing_returned_.Signal(); | 449 join_for_testing_returned_.Signal(); |
| 449 } | 450 } |
| 450 | 451 |
| 451 void SchedulerWorkerPoolImpl::DisallowWorkerDetachmentForTesting() { | 452 void SchedulerWorkerPoolImpl::DisallowWorkerDetachmentForTesting() { |
| 452 worker_detachment_disallowed_.Set(); | 453 worker_detachment_disallowed_.Set(); |
| 453 } | 454 } |
| 454 | 455 |
| 456 size_t SchedulerWorkerPoolImpl::NumberOfAliveWorkersForTesting() { |
| 457 size_t num_alive_workers = 0; |
| 458 for (const auto& worker : workers_) { |
| 459 if (worker->ThreadAliveForTesting()) |
| 460 ++num_alive_workers; |
| 461 } |
| 462 return num_alive_workers; |
| 463 } |
| 464 |
| 455 SchedulerWorkerPoolImpl::SchedulerSingleThreadTaskRunner:: | 465 SchedulerWorkerPoolImpl::SchedulerSingleThreadTaskRunner:: |
| 456 SchedulerSingleThreadTaskRunner(const TaskTraits& traits, | 466 SchedulerSingleThreadTaskRunner(const TaskTraits& traits, |
| 457 SchedulerWorkerPool* worker_pool, | 467 SchedulerWorkerPool* worker_pool, |
| 458 SchedulerWorker* worker) | 468 SchedulerWorker* worker) |
| 459 : traits_(traits), | 469 : traits_(traits), |
| 460 worker_pool_(worker_pool), | 470 worker_pool_(worker_pool), |
| 461 worker_(worker) { | 471 worker_(worker) { |
| 462 DCHECK(worker_pool_); | 472 DCHECK(worker_pool_); |
| 463 DCHECK(worker_); | 473 DCHECK(worker_); |
| 464 static_cast<SchedulerWorkerDelegateImpl*>(worker_->delegate())-> | 474 static_cast<SchedulerWorkerDelegateImpl*>(worker_->delegate())-> |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 50, | 719 50, |
| 710 HistogramBase::kUmaTargetedHistogramFlag)), | 720 HistogramBase::kUmaTargetedHistogramFlag)), |
| 711 task_tracker_(task_tracker), | 721 task_tracker_(task_tracker), |
| 712 delayed_task_manager_(delayed_task_manager) { | 722 delayed_task_manager_(delayed_task_manager) { |
| 713 DCHECK(task_tracker_); | 723 DCHECK(task_tracker_); |
| 714 DCHECK(delayed_task_manager_); | 724 DCHECK(delayed_task_manager_); |
| 715 } | 725 } |
| 716 | 726 |
| 717 bool SchedulerWorkerPoolImpl::Initialize( | 727 bool SchedulerWorkerPoolImpl::Initialize( |
| 718 ThreadPriority priority_hint, | 728 ThreadPriority priority_hint, |
| 729 SchedulerWorkerPoolParams::StandbyThreadPolicy standby_thread_policy, |
| 719 size_t max_threads, | 730 size_t max_threads, |
| 720 const ReEnqueueSequenceCallback& re_enqueue_sequence_callback) { | 731 const ReEnqueueSequenceCallback& re_enqueue_sequence_callback) { |
| 721 AutoSchedulerLock auto_lock(idle_workers_stack_lock_); | 732 AutoSchedulerLock auto_lock(idle_workers_stack_lock_); |
| 722 | 733 |
| 723 DCHECK(workers_.empty()); | 734 DCHECK(workers_.empty()); |
| 724 workers_.resize(max_threads); | 735 workers_.resize(max_threads); |
| 725 | 736 |
| 726 // Create workers and push them to the idle stack in reverse order of index. | 737 // Create workers and push them to the idle stack in reverse order of index. |
| 727 // This ensures that they are woken up in order of index and that the ALIVE | 738 // This ensures that they are woken up in order of index and that the ALIVE |
| 728 // worker is on top of the stack. | 739 // worker is on top of the stack. |
| 729 for (int index = max_threads - 1; index >= 0; --index) { | 740 for (int index = max_threads - 1; index >= 0; --index) { |
| 741 const bool is_standby_lazy = |
| 742 standby_thread_policy == |
| 743 SchedulerWorkerPoolParams::StandbyThreadPolicy::LAZY; |
| 730 const SchedulerWorker::InitialState initial_state = | 744 const SchedulerWorker::InitialState initial_state = |
| 731 (index == 0) ? SchedulerWorker::InitialState::ALIVE | 745 (index == 0 && !is_standby_lazy) |
| 732 : SchedulerWorker::InitialState::DETACHED; | 746 ? SchedulerWorker::InitialState::ALIVE |
| 747 : SchedulerWorker::InitialState::DETACHED; |
| 733 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( | 748 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| 734 priority_hint, | 749 priority_hint, |
| 735 MakeUnique<SchedulerWorkerDelegateImpl>( | 750 MakeUnique<SchedulerWorkerDelegateImpl>( |
| 736 this, re_enqueue_sequence_callback, &shared_priority_queue_, index), | 751 this, re_enqueue_sequence_callback, &shared_priority_queue_, index), |
| 737 task_tracker_, initial_state); | 752 task_tracker_, initial_state); |
| 738 if (!worker) | 753 if (!worker) |
| 739 break; | 754 break; |
| 740 idle_workers_stack_.Push(worker.get()); | 755 idle_workers_stack_.Push(worker.get()); |
| 741 workers_[index] = std::move(worker); | 756 workers_[index] = std::move(worker); |
| 742 } | 757 } |
| 743 | 758 |
| 744 #if DCHECK_IS_ON() | 759 #if DCHECK_IS_ON() |
| 745 workers_created_.Signal(); | 760 workers_created_.Signal(); |
| 746 #endif | 761 #endif |
| 747 | 762 |
| 748 return !workers_.empty(); | 763 return !workers_.empty(); |
| 749 } | 764 } |
| 750 | 765 |
| 751 void SchedulerWorkerPoolImpl::WakeUpWorker(SchedulerWorker* worker) { | 766 void SchedulerWorkerPoolImpl::WakeUpWorker(SchedulerWorker* worker) { |
| 752 DCHECK(worker); | 767 DCHECK(worker); |
| 753 RemoveFromIdleWorkersStack(worker); | 768 RemoveFromIdleWorkersStack(worker); |
| 754 worker->WakeUp(); | 769 worker->WakeUp(); |
| 770 // TOOD(robliao): Honor StandbyThreadPolicy::ONE here and consider adding |
| 771 // hysteresis to the CanDetach check. See https://crbug.com/666041. |
| 755 } | 772 } |
| 756 | 773 |
| 757 void SchedulerWorkerPoolImpl::WakeUpOneWorker() { | 774 void SchedulerWorkerPoolImpl::WakeUpOneWorker() { |
| 758 SchedulerWorker* worker; | 775 SchedulerWorker* worker; |
| 759 { | 776 { |
| 760 AutoSchedulerLock auto_lock(idle_workers_stack_lock_); | 777 AutoSchedulerLock auto_lock(idle_workers_stack_lock_); |
| 761 worker = idle_workers_stack_.Pop(); | 778 worker = idle_workers_stack_.Pop(); |
| 762 } | 779 } |
| 763 if (worker) | 780 if (worker) |
| 764 worker->WakeUp(); | 781 worker->WakeUp(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 790 AutoSchedulerLock auto_lock(idle_workers_stack_lock_); | 807 AutoSchedulerLock auto_lock(idle_workers_stack_lock_); |
| 791 idle_workers_stack_.Remove(worker); | 808 idle_workers_stack_.Remove(worker); |
| 792 } | 809 } |
| 793 | 810 |
| 794 bool SchedulerWorkerPoolImpl::CanWorkerDetachForTesting() { | 811 bool SchedulerWorkerPoolImpl::CanWorkerDetachForTesting() { |
| 795 return !worker_detachment_disallowed_.IsSet(); | 812 return !worker_detachment_disallowed_.IsSet(); |
| 796 } | 813 } |
| 797 | 814 |
| 798 } // namespace internal | 815 } // namespace internal |
| 799 } // namespace base | 816 } // namespace base |
| OLD | NEW |