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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 // Wait until all workers are idle to be sure that no task accesses | 320 // Wait until all workers are idle to be sure that no task accesses |
321 // its TestTaskFactory after it is destroyed. | 321 // its TestTaskFactory after it is destroyed. |
322 worker_pool_->WaitForAllWorkersIdleForTesting(); | 322 worker_pool_->WaitForAllWorkersIdleForTesting(); |
323 } | 323 } |
324 | 324 |
325 // Verify that a Task can't be posted after shutdown. | 325 // Verify that a Task can't be posted after shutdown. |
326 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTaskAfterShutdown) { | 326 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTaskAfterShutdown) { |
327 auto task_runner = | 327 auto task_runner = |
328 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); | 328 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); |
329 task_tracker_.Shutdown(); | 329 task_tracker_.Shutdown(); |
330 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, Bind(&ShouldNotRun))); | 330 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); |
331 } | 331 } |
332 | 332 |
333 // Verify that a Task runs shortly after its delay expires. | 333 // Verify that a Task runs shortly after its delay expires. |
334 TEST_P(TaskSchedulerWorkerPoolImplTest, PostDelayedTask) { | 334 TEST_P(TaskSchedulerWorkerPoolImplTest, PostDelayedTask) { |
335 TimeTicks start_time = TimeTicks::Now(); | 335 TimeTicks start_time = TimeTicks::Now(); |
336 | 336 |
337 // Post a task with a short delay. | 337 // Post a task with a short delay. |
338 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 338 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
339 WaitableEvent::InitialState::NOT_SIGNALED); | 339 WaitableEvent::InitialState::NOT_SIGNALED); |
340 EXPECT_TRUE(CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()) | 340 EXPECT_TRUE(CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()) |
341 ->PostDelayedTask(FROM_HERE, Bind(&WaitableEvent::Signal, | 341 ->PostDelayedTask( |
342 Unretained(&task_ran)), | 342 FROM_HERE, |
343 TestTimeouts::tiny_timeout())); | 343 BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)), |
| 344 TestTimeouts::tiny_timeout())); |
344 | 345 |
345 // Wait until the task runs. | 346 // Wait until the task runs. |
346 task_ran.Wait(); | 347 task_ran.Wait(); |
347 | 348 |
348 // Expect the task to run after its delay expires, but not more than 250 ms | 349 // Expect the task to run after its delay expires, but not more than 250 ms |
349 // after that. | 350 // after that. |
350 const TimeDelta actual_delay = TimeTicks::Now() - start_time; | 351 const TimeDelta actual_delay = TimeTicks::Now() - start_time; |
351 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); | 352 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); |
352 EXPECT_LT(actual_delay, | 353 EXPECT_LT(actual_delay, |
353 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); | 354 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); |
354 } | 355 } |
355 | 356 |
356 // Verify that the RunsTasksOnCurrentThread() method of a SEQUENCED TaskRunner | 357 // 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: | 358 // returns false when called from a task that isn't part of the sequence. Note: |
358 // Tests that use TestTaskFactory already verify that RunsTasksOnCurrentThread() | 359 // Tests that use TestTaskFactory already verify that RunsTasksOnCurrentThread() |
359 // returns true when appropriate so this method complements it to get full | 360 // returns true when appropriate so this method complements it to get full |
360 // coverage of that method. | 361 // coverage of that method. |
361 TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) { | 362 TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) { |
362 auto task_runner = | 363 auto task_runner = |
363 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); | 364 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); |
364 auto sequenced_task_runner = | 365 auto sequenced_task_runner = |
365 worker_pool_->CreateSequencedTaskRunnerWithTraits(TaskTraits()); | 366 worker_pool_->CreateSequencedTaskRunnerWithTraits(TaskTraits()); |
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 Bind( | 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(); |
376 }, | 377 }, |
377 sequenced_task_runner, Unretained(&task_ran))); | 378 sequenced_task_runner, Unretained(&task_ran))); |
378 task_ran.Wait(); | 379 task_ran.Wait(); |
379 } | 380 } |
380 | 381 |
381 INSTANTIATE_TEST_CASE_P(Parallel, | 382 INSTANTIATE_TEST_CASE_P(Parallel, |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 | 573 |
573 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { | 574 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { |
574 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, | 575 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
575 WaitableEvent::InitialState::NOT_SIGNALED); | 576 WaitableEvent::InitialState::NOT_SIGNALED); |
576 CreateAndStartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); | 577 CreateAndStartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); |
577 auto task_runner = worker_pool_->CreateSequencedTaskRunnerWithTraits( | 578 auto task_runner = worker_pool_->CreateSequencedTaskRunnerWithTraits( |
578 TaskTraits().WithBaseSyncPrimitives()); | 579 TaskTraits().WithBaseSyncPrimitives()); |
579 | 580 |
580 // Post a task. | 581 // Post a task. |
581 task_runner->PostTask(FROM_HERE, | 582 task_runner->PostTask(FROM_HERE, |
582 Bind(&WaitableEvent::Wait, Unretained(&event))); | 583 BindOnce(&WaitableEvent::Wait, Unretained(&event))); |
583 | 584 |
584 // Post 2 more tasks while the first task hasn't completed its execution. It | 585 // 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, | 586 // is guaranteed that these tasks will run immediately after the first task, |
586 // without allowing the worker to sleep. | 587 // without allowing the worker to sleep. |
587 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); | 588 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); |
588 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); | 589 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); |
589 | 590 |
590 // Allow tasks to run and wait until the SchedulerWorker is idle. | 591 // Allow tasks to run and wait until the SchedulerWorker is idle. |
591 event.Signal(); | 592 event.Signal(); |
592 worker_pool_->WaitForAllWorkersIdleForTesting(); | 593 worker_pool_->WaitForAllWorkersIdleForTesting(); |
593 | 594 |
594 // Wake up the SchedulerWorker that just became idle by posting a task and | 595 // Wake up the SchedulerWorker that just became idle by posting a task and |
595 // wait until it becomes idle again. The SchedulerWorker should record the | 596 // wait until it becomes idle again. The SchedulerWorker should record the |
596 // TaskScheduler.NumTasksBetweenWaits.* histogram on wake up. | 597 // TaskScheduler.NumTasksBetweenWaits.* histogram on wake up. |
597 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); | 598 task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing)); |
598 worker_pool_->WaitForAllWorkersIdleForTesting(); | 599 worker_pool_->WaitForAllWorkersIdleForTesting(); |
599 | 600 |
600 // Verify that counts were recorded to the histogram as expected. | 601 // Verify that counts were recorded to the histogram as expected. |
601 const auto* histogram = worker_pool_->num_tasks_between_waits_histogram(); | 602 const auto* histogram = worker_pool_->num_tasks_between_waits_histogram(); |
602 EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); | 603 EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); |
603 EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); | 604 EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); |
604 EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); | 605 EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); |
605 } | 606 } |
606 | 607 |
607 namespace { | 608 namespace { |
(...skipping 12 matching lines...) Expand all Loading... |
620 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); | 621 CreateAndStartWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); |
621 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( | 622 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( |
622 TaskTraits().WithBaseSyncPrimitives()); | 623 TaskTraits().WithBaseSyncPrimitives()); |
623 | 624 |
624 // Post tasks to saturate the pool. | 625 // Post tasks to saturate the pool. |
625 std::vector<std::unique_ptr<WaitableEvent>> task_started_events; | 626 std::vector<std::unique_ptr<WaitableEvent>> task_started_events; |
626 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 627 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
627 task_started_events.push_back( | 628 task_started_events.push_back( |
628 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, | 629 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, |
629 WaitableEvent::InitialState::NOT_SIGNALED)); | 630 WaitableEvent::InitialState::NOT_SIGNALED)); |
630 task_runner->PostTask( | 631 task_runner->PostTask(FROM_HERE, |
631 FROM_HERE, | 632 BindOnce(&SignalAndWaitEvent, |
632 Bind(&SignalAndWaitEvent, Unretained(task_started_events.back().get()), | 633 Unretained(task_started_events.back().get()), |
633 Unretained(&tasks_can_exit_event))); | 634 Unretained(&tasks_can_exit_event))); |
634 } | 635 } |
635 for (const auto& task_started_event : task_started_events) | 636 for (const auto& task_started_event : task_started_events) |
636 task_started_event->Wait(); | 637 task_started_event->Wait(); |
637 | 638 |
638 // Allow tasks to complete their execution and wait to allow workers to | 639 // Allow tasks to complete their execution and wait to allow workers to |
639 // detach. | 640 // detach. |
640 tasks_can_exit_event.Signal(); | 641 tasks_can_exit_event.Signal(); |
641 worker_pool_->WaitForAllWorkersIdleForTesting(); | 642 worker_pool_->WaitForAllWorkersIdleForTesting(); |
642 PlatformThread::Sleep(kReclaimTimeForDetachTests + kExtraTimeToWaitForDetach); | 643 PlatformThread::Sleep(kReclaimTimeForDetachTests + kExtraTimeToWaitForDetach); |
643 | 644 |
644 // Wake up SchedulerWorkers by posting tasks. They should record the | 645 // Wake up SchedulerWorkers by posting tasks. They should record the |
645 // TaskScheduler.NumTasksBetweenWaits.* histogram on wake up. | 646 // TaskScheduler.NumTasksBetweenWaits.* histogram on wake up. |
646 tasks_can_exit_event.Reset(); | 647 tasks_can_exit_event.Reset(); |
647 task_started_events.clear(); | 648 task_started_events.clear(); |
648 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 649 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
649 task_started_events.push_back( | 650 task_started_events.push_back( |
650 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, | 651 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, |
651 WaitableEvent::InitialState::NOT_SIGNALED)); | 652 WaitableEvent::InitialState::NOT_SIGNALED)); |
652 task_runner->PostTask( | 653 task_runner->PostTask(FROM_HERE, |
653 FROM_HERE, | 654 BindOnce(&SignalAndWaitEvent, |
654 Bind(&SignalAndWaitEvent, Unretained(task_started_events.back().get()), | 655 Unretained(task_started_events.back().get()), |
655 Unretained(&tasks_can_exit_event))); | 656 Unretained(&tasks_can_exit_event))); |
656 } | 657 } |
657 for (const auto& task_started_event : task_started_events) | 658 for (const auto& task_started_event : task_started_events) |
658 task_started_event->Wait(); | 659 task_started_event->Wait(); |
659 | 660 |
660 const auto* histogram = worker_pool_->num_tasks_between_waits_histogram(); | 661 const auto* histogram = worker_pool_->num_tasks_between_waits_histogram(); |
661 | 662 |
662 // Verify that counts were recorded to the histogram as expected. | 663 // Verify that counts were recorded to the histogram as expected. |
663 // - The "0" bucket has a count of at least 1 because the SchedulerWorker on | 664 // - The "0" bucket has a count of at least 1 because the SchedulerWorker on |
664 // top of the idle stack isn't allowed to detach when its sleep timeout | 665 // top of the idle stack isn't allowed to detach when its sleep timeout |
665 // expires. Instead, it waits on its WaitableEvent again without running a | 666 // expires. Instead, it waits on its WaitableEvent again without running a |
(...skipping 17 matching lines...) Expand all Loading... |
683 | 684 |
684 auto histogrammed_thread_task_runner = | 685 auto histogrammed_thread_task_runner = |
685 worker_pool_->CreateSequencedTaskRunnerWithTraits( | 686 worker_pool_->CreateSequencedTaskRunnerWithTraits( |
686 TaskTraits().WithBaseSyncPrimitives()); | 687 TaskTraits().WithBaseSyncPrimitives()); |
687 | 688 |
688 // Post 3 tasks and hold the thread for idle thread stack ordering. | 689 // Post 3 tasks and hold the thread for idle thread stack ordering. |
689 // This test assumes |histogrammed_thread_task_runner| gets assigned the same | 690 // This test assumes |histogrammed_thread_task_runner| gets assigned the same |
690 // thread for each of its tasks. | 691 // thread for each of its tasks. |
691 PlatformThreadRef thread_ref; | 692 PlatformThreadRef thread_ref; |
692 histogrammed_thread_task_runner->PostTask( | 693 histogrammed_thread_task_runner->PostTask( |
693 FROM_HERE, Bind( | 694 FROM_HERE, BindOnce( |
694 [](PlatformThreadRef* thread_ref) { | 695 [](PlatformThreadRef* thread_ref) { |
695 ASSERT_TRUE(thread_ref); | 696 ASSERT_TRUE(thread_ref); |
696 *thread_ref = PlatformThread::CurrentRef(); | 697 *thread_ref = PlatformThread::CurrentRef(); |
697 }, | 698 }, |
698 Unretained(&thread_ref))); | 699 Unretained(&thread_ref))); |
699 histogrammed_thread_task_runner->PostTask( | 700 histogrammed_thread_task_runner->PostTask( |
700 FROM_HERE, Bind( | 701 FROM_HERE, BindOnce( |
701 [](PlatformThreadRef* thread_ref) { | 702 [](PlatformThreadRef* thread_ref) { |
702 ASSERT_FALSE(thread_ref->is_null()); | 703 ASSERT_FALSE(thread_ref->is_null()); |
703 EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef()); | 704 EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef()); |
704 }, | 705 }, |
705 Unretained(&thread_ref))); | 706 Unretained(&thread_ref))); |
706 | 707 |
707 WaitableEvent detach_thread_running( | 708 WaitableEvent detach_thread_running( |
708 WaitableEvent::ResetPolicy::MANUAL, | 709 WaitableEvent::ResetPolicy::MANUAL, |
709 WaitableEvent::InitialState::NOT_SIGNALED); | 710 WaitableEvent::InitialState::NOT_SIGNALED); |
710 WaitableEvent detach_thread_continue( | 711 WaitableEvent detach_thread_continue( |
711 WaitableEvent::ResetPolicy::MANUAL, | 712 WaitableEvent::ResetPolicy::MANUAL, |
712 WaitableEvent::InitialState::NOT_SIGNALED); | 713 WaitableEvent::InitialState::NOT_SIGNALED); |
713 histogrammed_thread_task_runner->PostTask( | 714 histogrammed_thread_task_runner->PostTask( |
714 FROM_HERE, | 715 FROM_HERE, |
715 Bind( | 716 BindOnce( |
716 [](PlatformThreadRef* thread_ref, | 717 [](PlatformThreadRef* thread_ref, |
717 WaitableEvent* detach_thread_running, | 718 WaitableEvent* detach_thread_running, |
718 WaitableEvent* detach_thread_continue) { | 719 WaitableEvent* detach_thread_continue) { |
719 ASSERT_FALSE(thread_ref->is_null()); | 720 ASSERT_FALSE(thread_ref->is_null()); |
720 EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef()); | 721 EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef()); |
721 detach_thread_running->Signal(); | 722 detach_thread_running->Signal(); |
722 detach_thread_continue->Wait(); | 723 detach_thread_continue->Wait(); |
723 }, | 724 }, |
724 Unretained(&thread_ref), Unretained(&detach_thread_running), | 725 Unretained(&thread_ref), Unretained(&detach_thread_running), |
725 Unretained(&detach_thread_continue))); | 726 Unretained(&detach_thread_continue))); |
(...skipping 10 matching lines...) Expand all Loading... |
736 WaitableEvent top_idle_thread_running( | 737 WaitableEvent top_idle_thread_running( |
737 WaitableEvent::ResetPolicy::MANUAL, | 738 WaitableEvent::ResetPolicy::MANUAL, |
738 WaitableEvent::InitialState::NOT_SIGNALED); | 739 WaitableEvent::InitialState::NOT_SIGNALED); |
739 WaitableEvent top_idle_thread_continue( | 740 WaitableEvent top_idle_thread_continue( |
740 WaitableEvent::ResetPolicy::MANUAL, | 741 WaitableEvent::ResetPolicy::MANUAL, |
741 WaitableEvent::InitialState::NOT_SIGNALED); | 742 WaitableEvent::InitialState::NOT_SIGNALED); |
742 auto task_runner_for_top_idle = | 743 auto task_runner_for_top_idle = |
743 worker_pool_->CreateSequencedTaskRunnerWithTraits( | 744 worker_pool_->CreateSequencedTaskRunnerWithTraits( |
744 TaskTraits().WithBaseSyncPrimitives()); | 745 TaskTraits().WithBaseSyncPrimitives()); |
745 task_runner_for_top_idle->PostTask( | 746 task_runner_for_top_idle->PostTask( |
746 FROM_HERE, Bind( | 747 FROM_HERE, BindOnce( |
747 [](PlatformThreadRef thread_ref, | 748 [](PlatformThreadRef thread_ref, |
748 WaitableEvent* top_idle_thread_running, | 749 WaitableEvent* top_idle_thread_running, |
749 WaitableEvent* top_idle_thread_continue) { | 750 WaitableEvent* top_idle_thread_continue) { |
750 ASSERT_FALSE(thread_ref.is_null()); | 751 ASSERT_FALSE(thread_ref.is_null()); |
751 EXPECT_NE(thread_ref, PlatformThread::CurrentRef()) | 752 EXPECT_NE(thread_ref, PlatformThread::CurrentRef()) |
752 << "Worker reused. Thread will not detach and the " | 753 << "Worker reused. Thread will not detach and the " |
753 "histogram value will be wrong."; | 754 "histogram value will be wrong."; |
754 top_idle_thread_running->Signal(); | 755 top_idle_thread_running->Signal(); |
755 top_idle_thread_continue->Wait(); | 756 top_idle_thread_continue->Wait(); |
756 }, | 757 }, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 &delayed_task_manager); | 816 &delayed_task_manager); |
816 worker_pool->Start(SchedulerWorkerPoolParams(StandbyThreadPolicy::ONE, 8U, | 817 worker_pool->Start(SchedulerWorkerPoolParams(StandbyThreadPolicy::ONE, 8U, |
817 TimeDelta::Max())); | 818 TimeDelta::Max())); |
818 ASSERT_TRUE(worker_pool); | 819 ASSERT_TRUE(worker_pool); |
819 EXPECT_EQ(1U, worker_pool->NumberOfAliveWorkersForTesting()); | 820 EXPECT_EQ(1U, worker_pool->NumberOfAliveWorkersForTesting()); |
820 worker_pool->JoinForTesting(); | 821 worker_pool->JoinForTesting(); |
821 } | 822 } |
822 | 823 |
823 } // namespace internal | 824 } // namespace internal |
824 } // namespace base | 825 } // namespace base |
OLD | NEW |