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 |