| 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 <memory> | 9 #include <memory> |
| 10 #include <unordered_set> | 10 #include <unordered_set> |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 117 |
| 118 DelayedTaskManager delayed_task_manager_; | 118 DelayedTaskManager delayed_task_manager_; |
| 119 | 119 |
| 120 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTest); | 120 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTest); |
| 121 }; | 121 }; |
| 122 | 122 |
| 123 scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode( | 123 scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode( |
| 124 SchedulerWorkerPoolImpl* worker_pool, | 124 SchedulerWorkerPoolImpl* worker_pool, |
| 125 test::ExecutionMode execution_mode) { | 125 test::ExecutionMode execution_mode) { |
| 126 // Allow tasks posted to the returned TaskRunner to wait on a WaitableEvent. | 126 // Allow tasks posted to the returned TaskRunner to wait on a WaitableEvent. |
| 127 const TaskTraits traits = TaskTraits().WithBaseSyncPrimitives(); | 127 const TaskTraits traits = test::CreateTaskTraits().WithBaseSyncPrimitives(); |
| 128 switch (execution_mode) { | 128 switch (execution_mode) { |
| 129 case test::ExecutionMode::PARALLEL: | 129 case test::ExecutionMode::PARALLEL: |
| 130 return worker_pool->CreateTaskRunnerWithTraits(traits); | 130 return worker_pool->CreateTaskRunnerWithTraits(traits); |
| 131 case test::ExecutionMode::SEQUENCED: | 131 case test::ExecutionMode::SEQUENCED: |
| 132 return worker_pool->CreateSequencedTaskRunnerWithTraits(traits); | 132 return worker_pool->CreateSequencedTaskRunnerWithTraits(traits); |
| 133 default: | 133 default: |
| 134 // Fall through. | 134 // Fall through. |
| 135 break; | 135 break; |
| 136 } | 136 } |
| 137 ADD_FAILURE() << "Unexpected ExecutionMode"; | 137 ADD_FAILURE() << "Unexpected ExecutionMode"; |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 | 355 |
| 356 // Verify that the RunsTasksOnCurrentThread() method of a SEQUENCED TaskRunner | 356 // Verify that the RunsTasksOnCurrentThread() method of a SEQUENCED TaskRunner |
| 357 // returns false when called from a task that isn't part of the sequence. Note: | 357 // returns false when called from a task that isn't part of the sequence. Note: |
| 358 // Tests that use TestTaskFactory already verify that RunsTasksOnCurrentThread() | 358 // Tests that use TestTaskFactory already verify that RunsTasksOnCurrentThread() |
| 359 // returns true when appropriate so this method complements it to get full | 359 // returns true when appropriate so this method complements it to get full |
| 360 // coverage of that method. | 360 // coverage of that method. |
| 361 TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) { | 361 TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) { |
| 362 auto task_runner = | 362 auto task_runner = |
| 363 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); | 363 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); |
| 364 auto sequenced_task_runner = | 364 auto sequenced_task_runner = |
| 365 worker_pool_->CreateSequencedTaskRunnerWithTraits(TaskTraits()); | 365 worker_pool_->CreateSequencedTaskRunnerWithTraits( |
| 366 test::CreateTaskTraits()); |
| 366 | 367 |
| 367 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 368 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
| 368 WaitableEvent::InitialState::NOT_SIGNALED); | 369 WaitableEvent::InitialState::NOT_SIGNALED); |
| 369 task_runner->PostTask( | 370 task_runner->PostTask( |
| 370 FROM_HERE, | 371 FROM_HERE, |
| 371 BindOnce( | 372 BindOnce( |
| 372 [](scoped_refptr<TaskRunner> sequenced_task_runner, | 373 [](scoped_refptr<TaskRunner> sequenced_task_runner, |
| 373 WaitableEvent* task_ran) { | 374 WaitableEvent* task_ran) { |
| 374 EXPECT_FALSE(sequenced_task_runner->RunsTasksOnCurrentThread()); | 375 EXPECT_FALSE(sequenced_task_runner->RunsTasksOnCurrentThread()); |
| 375 task_ran->Signal(); | 376 task_ran->Signal(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 WaitableEvent task_2_scheduled(WaitableEvent::ResetPolicy::MANUAL, | 419 WaitableEvent task_2_scheduled(WaitableEvent::ResetPolicy::MANUAL, |
| 419 WaitableEvent::InitialState::NOT_SIGNALED); | 420 WaitableEvent::InitialState::NOT_SIGNALED); |
| 420 | 421 |
| 421 // This event is used to prevent a task from completing before the other task | 422 // This event is used to prevent a task from completing before the other task |
| 422 // is scheduled. If that happened, both tasks could run on the same worker and | 423 // is scheduled. If that happened, both tasks could run on the same worker and |
| 423 // this test couldn't verify that the correct number of workers were woken up. | 424 // this test couldn't verify that the correct number of workers were woken up. |
| 424 WaitableEvent barrier(WaitableEvent::ResetPolicy::MANUAL, | 425 WaitableEvent barrier(WaitableEvent::ResetPolicy::MANUAL, |
| 425 WaitableEvent::InitialState::NOT_SIGNALED); | 426 WaitableEvent::InitialState::NOT_SIGNALED); |
| 426 | 427 |
| 427 worker_pool_ | 428 worker_pool_ |
| 428 ->CreateTaskRunnerWithTraits(TaskTraits().WithBaseSyncPrimitives()) | 429 ->CreateTaskRunnerWithTraits( |
| 430 test::CreateTaskTraits().WithBaseSyncPrimitives()) |
| 429 ->PostTask(FROM_HERE, | 431 ->PostTask(FROM_HERE, |
| 430 Bind(&TaskPostedBeforeStart, Unretained(&task_1_thread_ref), | 432 Bind(&TaskPostedBeforeStart, Unretained(&task_1_thread_ref), |
| 431 Unretained(&task_1_scheduled), Unretained(&barrier))); | 433 Unretained(&task_1_scheduled), Unretained(&barrier))); |
| 432 worker_pool_ | 434 worker_pool_ |
| 433 ->CreateTaskRunnerWithTraits(TaskTraits().WithBaseSyncPrimitives()) | 435 ->CreateTaskRunnerWithTraits( |
| 436 test::CreateTaskTraits().WithBaseSyncPrimitives()) |
| 434 ->PostTask(FROM_HERE, | 437 ->PostTask(FROM_HERE, |
| 435 Bind(&TaskPostedBeforeStart, Unretained(&task_2_thread_ref), | 438 Bind(&TaskPostedBeforeStart, Unretained(&task_2_thread_ref), |
| 436 Unretained(&task_2_scheduled), Unretained(&barrier))); | 439 Unretained(&task_2_scheduled), Unretained(&barrier))); |
| 437 | 440 |
| 438 // Workers should not be created and tasks should not run before the pool is | 441 // Workers should not be created and tasks should not run before the pool is |
| 439 // started. | 442 // started. |
| 440 EXPECT_EQ(0U, worker_pool_->NumberOfAliveWorkersForTesting()); | 443 EXPECT_EQ(0U, worker_pool_->NumberOfAliveWorkersForTesting()); |
| 441 EXPECT_FALSE(task_1_scheduled.IsSignaled()); | 444 EXPECT_FALSE(task_1_scheduled.IsSignaled()); |
| 442 EXPECT_FALSE(task_2_scheduled.IsSignaled()); | 445 EXPECT_FALSE(task_2_scheduled.IsSignaled()); |
| 443 | 446 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 | 499 |
| 497 } // namespace | 500 } // namespace |
| 498 | 501 |
| 499 // Checks that at least one thread has detached by checking the TLS. | 502 // Checks that at least one thread has detached by checking the TLS. |
| 500 TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckDetachedThreads) { | 503 TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckDetachedThreads) { |
| 501 // Saturate the threads and mark each thread with a magic TLS value. | 504 // Saturate the threads and mark each thread with a magic TLS value. |
| 502 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; | 505 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; |
| 503 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 506 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
| 504 factories.push_back(MakeUnique<test::TestTaskFactory>( | 507 factories.push_back(MakeUnique<test::TestTaskFactory>( |
| 505 worker_pool_->CreateTaskRunnerWithTraits( | 508 worker_pool_->CreateTaskRunnerWithTraits( |
| 506 TaskTraits().WithBaseSyncPrimitives()), | 509 test::CreateTaskTraits().WithBaseSyncPrimitives()), |
| 507 test::ExecutionMode::PARALLEL)); | 510 test::ExecutionMode::PARALLEL)); |
| 508 ASSERT_TRUE(factories.back()->PostTask( | 511 ASSERT_TRUE(factories.back()->PostTask( |
| 509 PostNestedTask::NO, | 512 PostNestedTask::NO, |
| 510 Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait, | 513 Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait, |
| 511 Unretained(this)))); | 514 Unretained(this)))); |
| 512 factories.back()->WaitForAllTasksToRun(); | 515 factories.back()->WaitForAllTasksToRun(); |
| 513 } | 516 } |
| 514 | 517 |
| 515 // Release tasks waiting on |waiter_|. | 518 // Release tasks waiting on |waiter_|. |
| 516 waiter_.Signal(); | 519 waiter_.Signal(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolHistogramTest); | 571 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolHistogramTest); |
| 569 }; | 572 }; |
| 570 | 573 |
| 571 } // namespace | 574 } // namespace |
| 572 | 575 |
| 573 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { | 576 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { |
| 574 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, | 577 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 575 WaitableEvent::InitialState::NOT_SIGNALED); | 578 WaitableEvent::InitialState::NOT_SIGNALED); |
| 576 CreateAndStartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); | 579 CreateAndStartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); |
| 577 auto task_runner = worker_pool_->CreateSequencedTaskRunnerWithTraits( | 580 auto task_runner = worker_pool_->CreateSequencedTaskRunnerWithTraits( |
| 578 TaskTraits().WithBaseSyncPrimitives()); | 581 test::CreateTaskTraits().WithBaseSyncPrimitives()); |
| 579 | 582 |
| 580 // Post a task. | 583 // Post a task. |
| 581 task_runner->PostTask(FROM_HERE, | 584 task_runner->PostTask(FROM_HERE, |
| 582 BindOnce(&WaitableEvent::Wait, Unretained(&event))); | 585 BindOnce(&WaitableEvent::Wait, Unretained(&event))); |
| 583 | 586 |
| 584 // Post 2 more tasks while the first task hasn't completed its execution. It | 587 // Post 2 more tasks while the first task hasn't completed its execution. It |
| 585 // is guaranteed that these tasks will run immediately after the first task, | 588 // is guaranteed that these tasks will run immediately after the first task, |
| 586 // without allowing the worker to sleep. | 589 // without allowing the worker to sleep. |
| 587 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); | 590 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); |
| 588 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); | 591 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 612 wait_event->Wait(); | 615 wait_event->Wait(); |
| 613 } | 616 } |
| 614 | 617 |
| 615 } // namespace | 618 } // namespace |
| 616 | 619 |
| 617 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaitsWithDetach) { | 620 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaitsWithDetach) { |
| 618 WaitableEvent tasks_can_exit_event(WaitableEvent::ResetPolicy::MANUAL, | 621 WaitableEvent tasks_can_exit_event(WaitableEvent::ResetPolicy::MANUAL, |
| 619 WaitableEvent::InitialState::NOT_SIGNALED); | 622 WaitableEvent::InitialState::NOT_SIGNALED); |
| 620 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); | 623 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); |
| 621 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( | 624 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( |
| 622 TaskTraits().WithBaseSyncPrimitives()); | 625 test::CreateTaskTraits().WithBaseSyncPrimitives()); |
| 623 | 626 |
| 624 // Post tasks to saturate the pool. | 627 // Post tasks to saturate the pool. |
| 625 std::vector<std::unique_ptr<WaitableEvent>> task_started_events; | 628 std::vector<std::unique_ptr<WaitableEvent>> task_started_events; |
| 626 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 629 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
| 627 task_started_events.push_back( | 630 task_started_events.push_back( |
| 628 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, | 631 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, |
| 629 WaitableEvent::InitialState::NOT_SIGNALED)); | 632 WaitableEvent::InitialState::NOT_SIGNALED)); |
| 630 task_runner->PostTask(FROM_HERE, | 633 task_runner->PostTask(FROM_HERE, |
| 631 BindOnce(&SignalAndWaitEvent, | 634 BindOnce(&SignalAndWaitEvent, |
| 632 Unretained(task_started_events.back().get()), | 635 Unretained(task_started_events.back().get()), |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 tasks_can_exit_event.Signal(); | 679 tasks_can_exit_event.Signal(); |
| 677 worker_pool_->WaitForAllWorkersIdleForTesting(); | 680 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| 678 worker_pool_->DisallowWorkerDetachmentForTesting(); | 681 worker_pool_->DisallowWorkerDetachmentForTesting(); |
| 679 } | 682 } |
| 680 | 683 |
| 681 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { | 684 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { |
| 682 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); | 685 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); |
| 683 | 686 |
| 684 auto histogrammed_thread_task_runner = | 687 auto histogrammed_thread_task_runner = |
| 685 worker_pool_->CreateSequencedTaskRunnerWithTraits( | 688 worker_pool_->CreateSequencedTaskRunnerWithTraits( |
| 686 TaskTraits().WithBaseSyncPrimitives()); | 689 test::CreateTaskTraits().WithBaseSyncPrimitives()); |
| 687 | 690 |
| 688 // Post 3 tasks and hold the thread for idle thread stack ordering. | 691 // Post 3 tasks and hold the thread for idle thread stack ordering. |
| 689 // This test assumes |histogrammed_thread_task_runner| gets assigned the same | 692 // This test assumes |histogrammed_thread_task_runner| gets assigned the same |
| 690 // thread for each of its tasks. | 693 // thread for each of its tasks. |
| 691 PlatformThreadRef thread_ref; | 694 PlatformThreadRef thread_ref; |
| 692 histogrammed_thread_task_runner->PostTask( | 695 histogrammed_thread_task_runner->PostTask( |
| 693 FROM_HERE, BindOnce( | 696 FROM_HERE, BindOnce( |
| 694 [](PlatformThreadRef* thread_ref) { | 697 [](PlatformThreadRef* thread_ref) { |
| 695 ASSERT_TRUE(thread_ref); | 698 ASSERT_TRUE(thread_ref); |
| 696 *thread_ref = PlatformThread::CurrentRef(); | 699 *thread_ref = PlatformThread::CurrentRef(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 // release and go idle. This allows the SchedulerWorker associated with | 737 // release and go idle. This allows the SchedulerWorker associated with |
| 735 // |histogrammed_thread_task_runner| to detach. | 738 // |histogrammed_thread_task_runner| to detach. |
| 736 WaitableEvent top_idle_thread_running( | 739 WaitableEvent top_idle_thread_running( |
| 737 WaitableEvent::ResetPolicy::MANUAL, | 740 WaitableEvent::ResetPolicy::MANUAL, |
| 738 WaitableEvent::InitialState::NOT_SIGNALED); | 741 WaitableEvent::InitialState::NOT_SIGNALED); |
| 739 WaitableEvent top_idle_thread_continue( | 742 WaitableEvent top_idle_thread_continue( |
| 740 WaitableEvent::ResetPolicy::MANUAL, | 743 WaitableEvent::ResetPolicy::MANUAL, |
| 741 WaitableEvent::InitialState::NOT_SIGNALED); | 744 WaitableEvent::InitialState::NOT_SIGNALED); |
| 742 auto task_runner_for_top_idle = | 745 auto task_runner_for_top_idle = |
| 743 worker_pool_->CreateSequencedTaskRunnerWithTraits( | 746 worker_pool_->CreateSequencedTaskRunnerWithTraits( |
| 744 TaskTraits().WithBaseSyncPrimitives()); | 747 test::CreateTaskTraits().WithBaseSyncPrimitives()); |
| 745 task_runner_for_top_idle->PostTask( | 748 task_runner_for_top_idle->PostTask( |
| 746 FROM_HERE, BindOnce( | 749 FROM_HERE, BindOnce( |
| 747 [](PlatformThreadRef thread_ref, | 750 [](PlatformThreadRef thread_ref, |
| 748 WaitableEvent* top_idle_thread_running, | 751 WaitableEvent* top_idle_thread_running, |
| 749 WaitableEvent* top_idle_thread_continue) { | 752 WaitableEvent* top_idle_thread_continue) { |
| 750 ASSERT_FALSE(thread_ref.is_null()); | 753 ASSERT_FALSE(thread_ref.is_null()); |
| 751 EXPECT_NE(thread_ref, PlatformThread::CurrentRef()) | 754 EXPECT_NE(thread_ref, PlatformThread::CurrentRef()) |
| 752 << "Worker reused. Thread will not detach and the " | 755 << "Worker reused. Thread will not detach and the " |
| 753 "histogram value will be wrong."; | 756 "histogram value will be wrong."; |
| 754 top_idle_thread_running->Signal(); | 757 top_idle_thread_running->Signal(); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 &delayed_task_manager); | 818 &delayed_task_manager); |
| 816 worker_pool->Start(SchedulerWorkerPoolParams(StandbyThreadPolicy::ONE, 8U, | 819 worker_pool->Start(SchedulerWorkerPoolParams(StandbyThreadPolicy::ONE, 8U, |
| 817 TimeDelta::Max())); | 820 TimeDelta::Max())); |
| 818 ASSERT_TRUE(worker_pool); | 821 ASSERT_TRUE(worker_pool); |
| 819 EXPECT_EQ(1U, worker_pool->NumberOfAliveWorkersForTesting()); | 822 EXPECT_EQ(1U, worker_pool->NumberOfAliveWorkersForTesting()); |
| 820 worker_pool->JoinForTesting(); | 823 worker_pool->JoinForTesting(); |
| 821 } | 824 } |
| 822 | 825 |
| 823 } // namespace internal | 826 } // namespace internal |
| 824 } // namespace base | 827 } // namespace base |
| OLD | NEW |