| 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 private: | 106 private: |
| 107 DelayedTaskManager delayed_task_manager_; | 107 DelayedTaskManager delayed_task_manager_; |
| 108 | 108 |
| 109 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTest); | 109 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTest); |
| 110 }; | 110 }; |
| 111 | 111 |
| 112 scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode( | 112 scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode( |
| 113 SchedulerWorkerPoolImpl* worker_pool, | 113 SchedulerWorkerPoolImpl* worker_pool, |
| 114 test::ExecutionMode execution_mode) { | 114 test::ExecutionMode execution_mode) { |
| 115 // Allow tasks posted to the returned TaskRunner to wait on a WaitableEvent. | 115 // Allow tasks posted to the returned TaskRunner to wait on a WaitableEvent. |
| 116 const TaskTraits traits = TaskTraits().WithBaseSyncPrimitives(); | 116 const TaskTraits traits = {WithBaseSyncPrimitives()}; |
| 117 switch (execution_mode) { | 117 switch (execution_mode) { |
| 118 case test::ExecutionMode::PARALLEL: | 118 case test::ExecutionMode::PARALLEL: |
| 119 return worker_pool->CreateTaskRunnerWithTraits(traits); | 119 return worker_pool->CreateTaskRunnerWithTraits(traits); |
| 120 case test::ExecutionMode::SEQUENCED: | 120 case test::ExecutionMode::SEQUENCED: |
| 121 return worker_pool->CreateSequencedTaskRunnerWithTraits(traits); | 121 return worker_pool->CreateSequencedTaskRunnerWithTraits(traits); |
| 122 default: | 122 default: |
| 123 // Fall through. | 123 // Fall through. |
| 124 break; | 124 break; |
| 125 } | 125 } |
| 126 ADD_FAILURE() << "Unexpected ExecutionMode"; | 126 ADD_FAILURE() << "Unexpected ExecutionMode"; |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 WaitableEvent::InitialState::NOT_SIGNALED); | 406 WaitableEvent::InitialState::NOT_SIGNALED); |
| 407 WaitableEvent task_2_scheduled(WaitableEvent::ResetPolicy::MANUAL, | 407 WaitableEvent task_2_scheduled(WaitableEvent::ResetPolicy::MANUAL, |
| 408 WaitableEvent::InitialState::NOT_SIGNALED); | 408 WaitableEvent::InitialState::NOT_SIGNALED); |
| 409 | 409 |
| 410 // This event is used to prevent a task from completing before the other task | 410 // This event is used to prevent a task from completing before the other task |
| 411 // is scheduled. If that happened, both tasks could run on the same worker and | 411 // is scheduled. If that happened, both tasks could run on the same worker and |
| 412 // this test couldn't verify that the correct number of workers were woken up. | 412 // this test couldn't verify that the correct number of workers were woken up. |
| 413 WaitableEvent barrier(WaitableEvent::ResetPolicy::MANUAL, | 413 WaitableEvent barrier(WaitableEvent::ResetPolicy::MANUAL, |
| 414 WaitableEvent::InitialState::NOT_SIGNALED); | 414 WaitableEvent::InitialState::NOT_SIGNALED); |
| 415 | 415 |
| 416 worker_pool_ | 416 worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()}) |
| 417 ->CreateTaskRunnerWithTraits(TaskTraits().WithBaseSyncPrimitives()) | |
| 418 ->PostTask(FROM_HERE, | 417 ->PostTask(FROM_HERE, |
| 419 Bind(&TaskPostedBeforeStart, Unretained(&task_1_thread_ref), | 418 Bind(&TaskPostedBeforeStart, Unretained(&task_1_thread_ref), |
| 420 Unretained(&task_1_scheduled), Unretained(&barrier))); | 419 Unretained(&task_1_scheduled), Unretained(&barrier))); |
| 421 worker_pool_ | 420 worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()}) |
| 422 ->CreateTaskRunnerWithTraits(TaskTraits().WithBaseSyncPrimitives()) | |
| 423 ->PostTask(FROM_HERE, | 421 ->PostTask(FROM_HERE, |
| 424 Bind(&TaskPostedBeforeStart, Unretained(&task_2_thread_ref), | 422 Bind(&TaskPostedBeforeStart, Unretained(&task_2_thread_ref), |
| 425 Unretained(&task_2_scheduled), Unretained(&barrier))); | 423 Unretained(&task_2_scheduled), Unretained(&barrier))); |
| 426 | 424 |
| 427 // Workers should not be created and tasks should not run before the pool is | 425 // Workers should not be created and tasks should not run before the pool is |
| 428 // started. | 426 // started. |
| 429 EXPECT_EQ(0U, worker_pool_->NumberOfAliveWorkersForTesting()); | 427 EXPECT_EQ(0U, worker_pool_->NumberOfAliveWorkersForTesting()); |
| 430 EXPECT_FALSE(task_1_scheduled.IsSignaled()); | 428 EXPECT_FALSE(task_1_scheduled.IsSignaled()); |
| 431 EXPECT_FALSE(task_2_scheduled.IsSignaled()); | 429 EXPECT_FALSE(task_2_scheduled.IsSignaled()); |
| 432 | 430 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 }; | 482 }; |
| 485 | 483 |
| 486 } // namespace | 484 } // namespace |
| 487 | 485 |
| 488 // Checks that at least one thread has detached by checking the TLS. | 486 // Checks that at least one thread has detached by checking the TLS. |
| 489 TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckDetachedThreads) { | 487 TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckDetachedThreads) { |
| 490 // Saturate the threads and mark each thread with a magic TLS value. | 488 // Saturate the threads and mark each thread with a magic TLS value. |
| 491 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; | 489 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; |
| 492 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 490 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
| 493 factories.push_back(MakeUnique<test::TestTaskFactory>( | 491 factories.push_back(MakeUnique<test::TestTaskFactory>( |
| 494 worker_pool_->CreateTaskRunnerWithTraits( | 492 worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()}), |
| 495 TaskTraits().WithBaseSyncPrimitives()), | |
| 496 test::ExecutionMode::PARALLEL)); | 493 test::ExecutionMode::PARALLEL)); |
| 497 ASSERT_TRUE(factories.back()->PostTask( | 494 ASSERT_TRUE(factories.back()->PostTask( |
| 498 PostNestedTask::NO, | 495 PostNestedTask::NO, |
| 499 Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait, | 496 Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait, |
| 500 Unretained(this)))); | 497 Unretained(this)))); |
| 501 factories.back()->WaitForAllTasksToRun(); | 498 factories.back()->WaitForAllTasksToRun(); |
| 502 } | 499 } |
| 503 | 500 |
| 504 // Release tasks waiting on |waiter_|. | 501 // Release tasks waiting on |waiter_|. |
| 505 waiter_.Signal(); | 502 waiter_.Signal(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolHistogramTest); | 554 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolHistogramTest); |
| 558 }; | 555 }; |
| 559 | 556 |
| 560 } // namespace | 557 } // namespace |
| 561 | 558 |
| 562 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { | 559 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { |
| 563 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, | 560 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 564 WaitableEvent::InitialState::NOT_SIGNALED); | 561 WaitableEvent::InitialState::NOT_SIGNALED); |
| 565 CreateAndStartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); | 562 CreateAndStartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); |
| 566 auto task_runner = worker_pool_->CreateSequencedTaskRunnerWithTraits( | 563 auto task_runner = worker_pool_->CreateSequencedTaskRunnerWithTraits( |
| 567 TaskTraits().WithBaseSyncPrimitives()); | 564 {WithBaseSyncPrimitives()}); |
| 568 | 565 |
| 569 // Post a task. | 566 // Post a task. |
| 570 task_runner->PostTask(FROM_HERE, | 567 task_runner->PostTask(FROM_HERE, |
| 571 BindOnce(&WaitableEvent::Wait, Unretained(&event))); | 568 BindOnce(&WaitableEvent::Wait, Unretained(&event))); |
| 572 | 569 |
| 573 // Post 2 more tasks while the first task hasn't completed its execution. It | 570 // Post 2 more tasks while the first task hasn't completed its execution. It |
| 574 // is guaranteed that these tasks will run immediately after the first task, | 571 // is guaranteed that these tasks will run immediately after the first task, |
| 575 // without allowing the worker to sleep. | 572 // without allowing the worker to sleep. |
| 576 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); | 573 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); |
| 577 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); | 574 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 600 signal_event->Signal(); | 597 signal_event->Signal(); |
| 601 wait_event->Wait(); | 598 wait_event->Wait(); |
| 602 } | 599 } |
| 603 | 600 |
| 604 } // namespace | 601 } // namespace |
| 605 | 602 |
| 606 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaitsWithDetach) { | 603 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaitsWithDetach) { |
| 607 WaitableEvent tasks_can_exit_event(WaitableEvent::ResetPolicy::MANUAL, | 604 WaitableEvent tasks_can_exit_event(WaitableEvent::ResetPolicy::MANUAL, |
| 608 WaitableEvent::InitialState::NOT_SIGNALED); | 605 WaitableEvent::InitialState::NOT_SIGNALED); |
| 609 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); | 606 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); |
| 610 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( | 607 auto task_runner = |
| 611 TaskTraits().WithBaseSyncPrimitives()); | 608 worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()}); |
| 612 | 609 |
| 613 // Post tasks to saturate the pool. | 610 // Post tasks to saturate the pool. |
| 614 std::vector<std::unique_ptr<WaitableEvent>> task_started_events; | 611 std::vector<std::unique_ptr<WaitableEvent>> task_started_events; |
| 615 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 612 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
| 616 task_started_events.push_back( | 613 task_started_events.push_back( |
| 617 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, | 614 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, |
| 618 WaitableEvent::InitialState::NOT_SIGNALED)); | 615 WaitableEvent::InitialState::NOT_SIGNALED)); |
| 619 task_runner->PostTask(FROM_HERE, | 616 task_runner->PostTask(FROM_HERE, |
| 620 BindOnce(&SignalAndWaitEvent, | 617 BindOnce(&SignalAndWaitEvent, |
| 621 Unretained(task_started_events.back().get()), | 618 Unretained(task_started_events.back().get()), |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 tasks_can_exit_event.Signal(); | 662 tasks_can_exit_event.Signal(); |
| 666 worker_pool_->WaitForAllWorkersIdleForTesting(); | 663 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| 667 worker_pool_->DisallowWorkerDetachmentForTesting(); | 664 worker_pool_->DisallowWorkerDetachmentForTesting(); |
| 668 } | 665 } |
| 669 | 666 |
| 670 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { | 667 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { |
| 671 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); | 668 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); |
| 672 | 669 |
| 673 auto histogrammed_thread_task_runner = | 670 auto histogrammed_thread_task_runner = |
| 674 worker_pool_->CreateSequencedTaskRunnerWithTraits( | 671 worker_pool_->CreateSequencedTaskRunnerWithTraits( |
| 675 TaskTraits().WithBaseSyncPrimitives()); | 672 {WithBaseSyncPrimitives()}); |
| 676 | 673 |
| 677 // Post 3 tasks and hold the thread for idle thread stack ordering. | 674 // Post 3 tasks and hold the thread for idle thread stack ordering. |
| 678 // This test assumes |histogrammed_thread_task_runner| gets assigned the same | 675 // This test assumes |histogrammed_thread_task_runner| gets assigned the same |
| 679 // thread for each of its tasks. | 676 // thread for each of its tasks. |
| 680 PlatformThreadRef thread_ref; | 677 PlatformThreadRef thread_ref; |
| 681 histogrammed_thread_task_runner->PostTask( | 678 histogrammed_thread_task_runner->PostTask( |
| 682 FROM_HERE, BindOnce( | 679 FROM_HERE, BindOnce( |
| 683 [](PlatformThreadRef* thread_ref) { | 680 [](PlatformThreadRef* thread_ref) { |
| 684 ASSERT_TRUE(thread_ref); | 681 ASSERT_TRUE(thread_ref); |
| 685 *thread_ref = PlatformThread::CurrentRef(); | 682 *thread_ref = PlatformThread::CurrentRef(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 // release and go idle. This allows the SchedulerWorker associated with | 720 // release and go idle. This allows the SchedulerWorker associated with |
| 724 // |histogrammed_thread_task_runner| to detach. | 721 // |histogrammed_thread_task_runner| to detach. |
| 725 WaitableEvent top_idle_thread_running( | 722 WaitableEvent top_idle_thread_running( |
| 726 WaitableEvent::ResetPolicy::MANUAL, | 723 WaitableEvent::ResetPolicy::MANUAL, |
| 727 WaitableEvent::InitialState::NOT_SIGNALED); | 724 WaitableEvent::InitialState::NOT_SIGNALED); |
| 728 WaitableEvent top_idle_thread_continue( | 725 WaitableEvent top_idle_thread_continue( |
| 729 WaitableEvent::ResetPolicy::MANUAL, | 726 WaitableEvent::ResetPolicy::MANUAL, |
| 730 WaitableEvent::InitialState::NOT_SIGNALED); | 727 WaitableEvent::InitialState::NOT_SIGNALED); |
| 731 auto task_runner_for_top_idle = | 728 auto task_runner_for_top_idle = |
| 732 worker_pool_->CreateSequencedTaskRunnerWithTraits( | 729 worker_pool_->CreateSequencedTaskRunnerWithTraits( |
| 733 TaskTraits().WithBaseSyncPrimitives()); | 730 {WithBaseSyncPrimitives()}); |
| 734 task_runner_for_top_idle->PostTask( | 731 task_runner_for_top_idle->PostTask( |
| 735 FROM_HERE, BindOnce( | 732 FROM_HERE, BindOnce( |
| 736 [](PlatformThreadRef thread_ref, | 733 [](PlatformThreadRef thread_ref, |
| 737 WaitableEvent* top_idle_thread_running, | 734 WaitableEvent* top_idle_thread_running, |
| 738 WaitableEvent* top_idle_thread_continue) { | 735 WaitableEvent* top_idle_thread_continue) { |
| 739 ASSERT_FALSE(thread_ref.is_null()); | 736 ASSERT_FALSE(thread_ref.is_null()); |
| 740 EXPECT_NE(thread_ref, PlatformThread::CurrentRef()) | 737 EXPECT_NE(thread_ref, PlatformThread::CurrentRef()) |
| 741 << "Worker reused. Thread will not detach and the " | 738 << "Worker reused. Thread will not detach and the " |
| 742 "histogram value will be wrong."; | 739 "histogram value will be wrong."; |
| 743 top_idle_thread_running->Signal(); | 740 top_idle_thread_running->Signal(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 &delayed_task_manager); | 790 &delayed_task_manager); |
| 794 worker_pool->Start(SchedulerWorkerPoolParams(StandbyThreadPolicy::ONE, 8U, | 791 worker_pool->Start(SchedulerWorkerPoolParams(StandbyThreadPolicy::ONE, 8U, |
| 795 TimeDelta::Max())); | 792 TimeDelta::Max())); |
| 796 ASSERT_TRUE(worker_pool); | 793 ASSERT_TRUE(worker_pool); |
| 797 EXPECT_EQ(1U, worker_pool->NumberOfAliveWorkersForTesting()); | 794 EXPECT_EQ(1U, worker_pool->NumberOfAliveWorkersForTesting()); |
| 798 worker_pool->JoinForTesting(); | 795 worker_pool->JoinForTesting(); |
| 799 } | 796 } |
| 800 | 797 |
| 801 } // namespace internal | 798 } // namespace internal |
| 802 } // namespace base | 799 } // namespace base |
| OLD | NEW |