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 |