OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/threading/sequenced_worker_pool.h" | 5 #include "base/threading/sequenced_worker_pool.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <memory> | 10 #include <memory> |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | 589 SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
590 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( | 590 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( |
591 FROM_HERE, | 591 FROM_HERE, |
592 base::Bind(&TestTracker::FastTask, tracker(), 102), | 592 base::Bind(&TestTracker::FastTask, tracker(), 102), |
593 SequencedWorkerPool::BLOCK_SHUTDOWN)); | 593 SequencedWorkerPool::BLOCK_SHUTDOWN)); |
594 | 594 |
595 ASSERT_EQ(old_has_work_call_count, has_work_call_count()); | 595 ASSERT_EQ(old_has_work_call_count, has_work_call_count()); |
596 } | 596 } |
597 | 597 |
598 TEST_P(SequencedWorkerPoolTest, AllowsAfterShutdown) { | 598 TEST_P(SequencedWorkerPoolTest, AllowsAfterShutdown) { |
599 // As tested by TaskSchedulerTaskTrackerTest.WillPostAndRunDuringShutdown, | |
600 // TaskScheduler allows tasks to be posted during shutdown. However, since it | |
601 // doesn't provide a way to run a callback from inside its Shutdown() method, | |
602 // it would be hard to make this test work with redirection enabled. | |
603 if (RedirectedToTaskScheduler()) | |
604 return; | |
605 | |
606 // Test that <n> new blocking tasks are allowed provided they're posted | 599 // Test that <n> new blocking tasks are allowed provided they're posted |
607 // by a running tasks. | 600 // by a running tasks. |
608 EnsureAllWorkersCreated(); | 601 EnsureAllWorkersCreated(); |
609 ThreadBlocker blocker; | 602 ThreadBlocker blocker; |
610 | 603 |
611 // Start tasks to take all the threads and block them. | 604 // Start tasks to take all the threads and block them. |
612 const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); | 605 const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); |
613 for (int i = 0; i < kNumBlockTasks; ++i) { | 606 for (int i = 0; i < kNumBlockTasks; ++i) { |
614 EXPECT_TRUE(pool()->PostWorkerTask( | 607 EXPECT_TRUE(pool()->PostWorkerTask( |
615 FROM_HERE, | 608 FROM_HERE, |
616 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); | 609 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); |
617 } | 610 } |
618 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); | 611 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
619 | 612 |
620 // Queue up shutdown blocking tasks behind those which will attempt to post | 613 // Queue up shutdown blocking tasks behind those which will attempt to post |
621 // additional tasks when run, PostAdditionalTasks attemtps to post 3 | 614 // additional tasks when run, PostAdditionalTasks attempts to post 3 |
622 // new FastTasks, one for each shutdown_behavior. | 615 // new FastTasks, one for each shutdown_behavior. |
623 const int kNumQueuedTasks = static_cast<int>(kNumWorkerThreads); | 616 const int kNumQueuedTasks = static_cast<int>(kNumWorkerThreads); |
624 for (int i = 0; i < kNumQueuedTasks; ++i) { | 617 for (int i = 0; i < kNumQueuedTasks; ++i) { |
625 EXPECT_TRUE(pool()->PostWorkerTaskWithShutdownBehavior( | 618 EXPECT_TRUE(pool()->PostWorkerTaskWithShutdownBehavior( |
626 FROM_HERE, base::Bind(&TestTracker::PostAdditionalTasks, tracker(), i, | 619 FROM_HERE, base::Bind(&TestTracker::PostAdditionalTasks, tracker(), i, |
627 base::RetainedRef(pool()), false), | 620 base::RetainedRef(pool()), false), |
628 SequencedWorkerPool::BLOCK_SHUTDOWN)); | 621 SequencedWorkerPool::BLOCK_SHUTDOWN)); |
629 } | 622 } |
630 | 623 |
631 // Setup to open the floodgates from within Shutdown(). | 624 // Half the additional blocking tasks will be allowed to run. |
632 SetWillWaitForShutdownCallback( | 625 constexpr int kNumNewBlockingTasksToAllow = kNumWorkerThreads / 2; |
633 base::Bind(&EnsureTasksToCompleteCountAndUnblock, | |
634 scoped_refptr<TestTracker>(tracker()), | |
635 0, &blocker, kNumBlockTasks)); | |
636 | 626 |
637 // Allow half of the additional blocking tasks thru. | 627 if (RedirectedToTaskScheduler()) { |
638 const int kNumNewBlockingTasksToAllow = kNumWorkerThreads / 2; | 628 // When redirection to TaskScheduler is enabled, |
639 pool()->Shutdown(kNumNewBlockingTasksToAllow); | 629 // SequencedWorkerPool::Shutdown() sets the number of additional |
| 630 // BLOCK_SHUTDOWN tasks that can be posted and returns without waiting for |
| 631 // pending BLOCK_SHUTDOWN tasks to complete their execution. |
| 632 pool()->Shutdown(kNumNewBlockingTasksToAllow); |
| 633 |
| 634 // Unblock tasks. |
| 635 EnsureTasksToCompleteCountAndUnblock(tracker(), 0, &blocker, |
| 636 kNumBlockTasks); |
| 637 |
| 638 // TaskScheduler::Shutdown() waits for pending BLOCK_SHUTDOWN tasks to |
| 639 // complete their execution. |
| 640 TaskScheduler::GetInstance()->Shutdown(); |
| 641 } else { |
| 642 // Once shutdown starts, unblock tasks. |
| 643 SetWillWaitForShutdownCallback(base::Bind( |
| 644 &EnsureTasksToCompleteCountAndUnblock, |
| 645 scoped_refptr<TestTracker>(tracker()), 0, &blocker, kNumBlockTasks)); |
| 646 |
| 647 // Set the number of additional BLOCK_SHUTDOWN tasks that can be posted and |
| 648 // wait for pending BLOCK_SHUTDOWN tasks to complete their execution. |
| 649 pool()->Shutdown(kNumNewBlockingTasksToAllow); |
| 650 } |
640 | 651 |
641 // Ensure that the correct number of tasks actually got run. | 652 // Ensure that the correct number of tasks actually got run. |
642 tracker()->WaitUntilTasksComplete(static_cast<size_t>( | 653 tracker()->WaitUntilTasksComplete(static_cast<size_t>( |
643 kNumBlockTasks + kNumQueuedTasks + kNumNewBlockingTasksToAllow)); | 654 kNumBlockTasks + kNumQueuedTasks + kNumNewBlockingTasksToAllow)); |
644 | 655 |
645 // Clean up the task IDs we added and go home. | 656 // Clean up the task IDs we added and go home. |
646 tracker()->ClearCompleteSequence(); | 657 tracker()->ClearCompleteSequence(); |
647 } | 658 } |
648 | 659 |
649 // Tests that blocking tasks can still be posted during shutdown, as long as | 660 // Tests that blocking tasks can still be posted during shutdown, as long as |
650 // the task is not being posted within the context of a running task. | 661 // the task is not being posted within the context of a running task. |
651 TEST_P(SequencedWorkerPoolTest, | 662 TEST_P(SequencedWorkerPoolTest, |
652 AllowsBlockingTasksDuringShutdownOutsideOfRunningTask) { | 663 AllowsBlockingTasksDuringShutdownOutsideOfRunningTask) { |
653 // As tested by TaskSchedulerTaskTrackerTest.WillPostAndRunDuringShutdown, | |
654 // TaskScheduler allows tasks to be posted during shutdown. However, since it | |
655 // doesn't provide a way to run a callback from inside its Shutdown() method, | |
656 // it would be hard to make this test work with redirection enabled. | |
657 if (RedirectedToTaskScheduler()) | |
658 return; | |
659 | |
660 EnsureAllWorkersCreated(); | 664 EnsureAllWorkersCreated(); |
661 ThreadBlocker blocker; | 665 ThreadBlocker blocker; |
662 | 666 |
663 // Start tasks to take all the threads and block them. | 667 // Start tasks to take all the threads and block them. |
664 const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); | 668 const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); |
665 for (int i = 0; i < kNumBlockTasks; ++i) { | 669 for (int i = 0; i < kNumBlockTasks; ++i) { |
666 EXPECT_TRUE(pool()->PostWorkerTask( | 670 EXPECT_TRUE(pool()->PostWorkerTask( |
667 FROM_HERE, | 671 FROM_HERE, |
668 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); | 672 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); |
669 } | 673 } |
670 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); | 674 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
671 | 675 |
672 // Setup to open the floodgates from within Shutdown(). | 676 constexpr int kNumNewBlockingTasksToAllow = 1; |
673 SetWillWaitForShutdownCallback( | 677 |
674 base::Bind(&TestTracker::PostBlockingTaskThenUnblockThreads, | 678 if (RedirectedToTaskScheduler()) { |
675 scoped_refptr<TestTracker>(tracker()), pool(), &blocker, | 679 // When redirection to TaskScheduler is enabled, |
676 kNumWorkerThreads)); | 680 // SequencedWorkerPool::Shutdown() sets the number of additional |
677 pool()->Shutdown(kNumWorkerThreads + 1); | 681 // BLOCK_SHUTDOWN tasks that can be posted and returns without waiting for |
| 682 // pending BLOCK_SHUTDOWN tasks to complete their execution. |
| 683 pool()->Shutdown(kNumNewBlockingTasksToAllow); |
| 684 |
| 685 // Post a blocking task and unblock tasks. |
| 686 tracker()->PostBlockingTaskThenUnblockThreads(pool(), &blocker, |
| 687 kNumWorkerThreads); |
| 688 |
| 689 // TaskScheduler::Shutdown() waits for pending BLOCK_SHUTDOWN tasks to |
| 690 // complete their execution. |
| 691 TaskScheduler::GetInstance()->Shutdown(); |
| 692 } else { |
| 693 // Once shutdown starts, post a blocking task and unblock tasks. |
| 694 SetWillWaitForShutdownCallback( |
| 695 base::Bind(&TestTracker::PostBlockingTaskThenUnblockThreads, |
| 696 scoped_refptr<TestTracker>(tracker()), pool(), &blocker, |
| 697 kNumWorkerThreads)); |
| 698 |
| 699 // Set the number of additional BLOCK_SHUTDOWN tasks that can be posted and |
| 700 // wait for pending BLOCK_SHUTDOWN tasks to complete their execution. |
| 701 pool()->Shutdown(kNumNewBlockingTasksToAllow); |
| 702 } |
678 | 703 |
679 // Ensure that the correct number of tasks actually got run. | 704 // Ensure that the correct number of tasks actually got run. |
680 tracker()->WaitUntilTasksComplete(static_cast<size_t>(kNumWorkerThreads + 1)); | 705 tracker()->WaitUntilTasksComplete( |
| 706 static_cast<size_t>(kNumWorkerThreads + kNumNewBlockingTasksToAllow)); |
681 tracker()->ClearCompleteSequence(); | 707 tracker()->ClearCompleteSequence(); |
682 } | 708 } |
683 | 709 |
684 // Tests that unrun tasks are discarded properly according to their shutdown | 710 // Tests that unrun tasks are discarded properly according to their shutdown |
685 // mode. | 711 // mode. |
686 TEST_P(SequencedWorkerPoolTest, DiscardOnShutdown) { | 712 TEST_P(SequencedWorkerPoolTest, DiscardOnShutdown) { |
687 // As tested by | 713 // As tested by |
688 // TaskSchedulerTaskTrackerTest.WillPostBeforeShutdownRunDuringShutdown, on | 714 // TaskSchedulerTaskTrackerTest.WillPostBeforeShutdownRunDuringShutdown, on |
689 // shutdown, the TaskScheduler discards SKIP_ON_SHUTDOWN and | 715 // shutdown, the TaskScheduler discards SKIP_ON_SHUTDOWN and |
690 // CONTINUE_ON_SHUTDOWN tasks and runs BLOCK_SHUTDOWN tasks. However, since it | 716 // CONTINUE_ON_SHUTDOWN tasks and runs BLOCK_SHUTDOWN tasks. However, since it |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, | 1231 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, |
1206 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 1232 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
1207 INSTANTIATE_TYPED_TEST_CASE_P( | 1233 INSTANTIATE_TYPED_TEST_CASE_P( |
1208 SequencedWorkerPoolSequencedTaskRunner, | 1234 SequencedWorkerPoolSequencedTaskRunner, |
1209 SequencedTaskRunnerDelayedTest, | 1235 SequencedTaskRunnerDelayedTest, |
1210 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 1236 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
1211 | 1237 |
1212 } // namespace | 1238 } // namespace |
1213 | 1239 |
1214 } // namespace base | 1240 } // namespace base |
OLD | NEW |