| 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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 size_t started_events_; | 227 size_t started_events_; |
| 228 }; | 228 }; |
| 229 | 229 |
| 230 class SequencedWorkerPoolTest : public testing::Test { | 230 class SequencedWorkerPoolTest : public testing::Test { |
| 231 public: | 231 public: |
| 232 SequencedWorkerPoolTest() | 232 SequencedWorkerPoolTest() |
| 233 : tracker_(new TestTracker) { | 233 : tracker_(new TestTracker) { |
| 234 ResetPool(); | 234 ResetPool(); |
| 235 } | 235 } |
| 236 | 236 |
| 237 void TearDown() override { pool()->Shutdown(); } |
| 238 |
| 237 const scoped_refptr<SequencedWorkerPool>& pool() { | 239 const scoped_refptr<SequencedWorkerPool>& pool() { |
| 238 return pool_owner_->pool(); | 240 return pool_owner_->pool(); |
| 239 } | 241 } |
| 240 TestTracker* tracker() { return tracker_.get(); } | 242 TestTracker* tracker() { return tracker_.get(); } |
| 241 | 243 |
| 242 // Destroys the SequencedWorkerPool instance, blocking until it is fully shut | 244 // Destroys the SequencedWorkerPool instance, blocking until it is fully shut |
| 243 // down, and creates a new instance. | 245 // down, and creates a new instance. |
| 244 void ResetPool() { | 246 void ResetPool() { |
| 245 pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test")); | 247 pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test")); |
| 246 } | 248 } |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 FROM_HERE, | 344 FROM_HERE, |
| 343 base::Bind(&HoldPoolReference, | 345 base::Bind(&HoldPoolReference, |
| 344 pool(), | 346 pool(), |
| 345 make_scoped_refptr(new DeletionHelper(deleted_flag))), | 347 make_scoped_refptr(new DeletionHelper(deleted_flag))), |
| 346 TestTimeouts::action_timeout())); | 348 TestTimeouts::action_timeout())); |
| 347 | 349 |
| 348 std::vector<int> completion_sequence = tracker()->WaitUntilTasksComplete(1); | 350 std::vector<int> completion_sequence = tracker()->WaitUntilTasksComplete(1); |
| 349 ASSERT_EQ(1u, completion_sequence.size()); | 351 ASSERT_EQ(1u, completion_sequence.size()); |
| 350 ASSERT_EQ(1, completion_sequence[0]); | 352 ASSERT_EQ(1, completion_sequence[0]); |
| 351 | 353 |
| 354 pool()->Shutdown(); |
| 352 // Shutdown is asynchronous, so use ResetPool() to block until the pool is | 355 // Shutdown is asynchronous, so use ResetPool() to block until the pool is |
| 353 // fully destroyed (and thus shut down). | 356 // fully destroyed (and thus shut down). |
| 354 ResetPool(); | 357 ResetPool(); |
| 355 | 358 |
| 356 // Verify that we didn't block until the task was due. | 359 // Verify that we didn't block until the task was due. |
| 357 ASSERT_LT(base::Time::Now() - posted_at, TestTimeouts::action_timeout()); | 360 ASSERT_LT(base::Time::Now() - posted_at, TestTimeouts::action_timeout()); |
| 358 | 361 |
| 359 // Verify that the deferred task has not only not run, but has also been | 362 // Verify that the deferred task has not only not run, but has also been |
| 360 // destroyed. | 363 // destroyed. |
| 361 ASSERT_TRUE(deleted_flag->data); | 364 ASSERT_TRUE(deleted_flag->data); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 for (size_t i = 1; i < kNumTasks; i++) { | 423 for (size_t i = 1; i < kNumTasks; i++) { |
| 421 base::Closure fast_task = | 424 base::Closure fast_task = |
| 422 base::Bind(&TestTracker::FastTask, tracker(), i); | 425 base::Bind(&TestTracker::FastTask, tracker(), i); |
| 423 pool1.pool()->PostWorkerTask(FROM_HERE, fast_task); | 426 pool1.pool()->PostWorkerTask(FROM_HERE, fast_task); |
| 424 pool2.pool()->PostWorkerTask(FROM_HERE, fast_task); | 427 pool2.pool()->PostWorkerTask(FROM_HERE, fast_task); |
| 425 } | 428 } |
| 426 | 429 |
| 427 std::vector<int> result = | 430 std::vector<int> result = |
| 428 tracker()->WaitUntilTasksComplete(2*kNumTasks); | 431 tracker()->WaitUntilTasksComplete(2*kNumTasks); |
| 429 EXPECT_EQ(2 * kNumTasks, result.size()); | 432 EXPECT_EQ(2 * kNumTasks, result.size()); |
| 433 |
| 434 pool2.pool()->Shutdown(); |
| 435 pool1.pool()->Shutdown(); |
| 430 } | 436 } |
| 431 | 437 |
| 432 // Test that tasks with the same sequence token are executed in order but don't | 438 // Test that tasks with the same sequence token are executed in order but don't |
| 433 // affect other tasks. | 439 // affect other tasks. |
| 434 TEST_F(SequencedWorkerPoolTest, Sequence) { | 440 TEST_F(SequencedWorkerPoolTest, Sequence) { |
| 435 // Fill all the worker threads except one. | 441 // Fill all the worker threads except one. |
| 436 const size_t kNumBackgroundTasks = kNumWorkerThreads - 1; | 442 const size_t kNumBackgroundTasks = kNumWorkerThreads - 1; |
| 437 ThreadBlocker background_blocker; | 443 ThreadBlocker background_blocker; |
| 438 for (size_t i = 0; i < kNumBackgroundTasks; i++) { | 444 for (size_t i = 0; i < kNumBackgroundTasks; i++) { |
| 439 pool()->PostWorkerTask(FROM_HERE, | 445 pool()->PostWorkerTask(FROM_HERE, |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 EXPECT_FALSE( | 792 EXPECT_FALSE( |
| 787 unused_pool->IsRunningSequenceOnCurrentThread(test_negative_token)); | 793 unused_pool->IsRunningSequenceOnCurrentThread(test_negative_token)); |
| 788 } | 794 } |
| 789 | 795 |
| 790 // Verify correctness of the IsRunningSequenceOnCurrentThread method. | 796 // Verify correctness of the IsRunningSequenceOnCurrentThread method. |
| 791 TEST_F(SequencedWorkerPoolTest, IsRunningOnCurrentThread) { | 797 TEST_F(SequencedWorkerPoolTest, IsRunningOnCurrentThread) { |
| 792 SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); | 798 SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); |
| 793 SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); | 799 SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); |
| 794 SequencedWorkerPool::SequenceToken unsequenced_token; | 800 SequencedWorkerPool::SequenceToken unsequenced_token; |
| 795 | 801 |
| 796 SequencedWorkerPoolOwner unused_pool_owner(2, "unused_pool"); | 802 scoped_refptr<SequencedWorkerPool> unused_pool = |
| 803 new SequencedWorkerPool(2, "unused_pool"); |
| 797 | 804 |
| 798 EXPECT_FALSE(pool()->RunsTasksOnCurrentThread()); | 805 EXPECT_FALSE(pool()->RunsTasksOnCurrentThread()); |
| 799 EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token1)); | 806 EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token1)); |
| 800 EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token2)); | 807 EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token2)); |
| 801 EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(unsequenced_token)); | 808 EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(unsequenced_token)); |
| 802 EXPECT_FALSE(unused_pool_owner.pool()->RunsTasksOnCurrentThread()); | 809 EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread()); |
| 810 EXPECT_FALSE(unused_pool->IsRunningSequenceOnCurrentThread(token1)); |
| 811 EXPECT_FALSE(unused_pool->IsRunningSequenceOnCurrentThread(token2)); |
| 803 EXPECT_FALSE( | 812 EXPECT_FALSE( |
| 804 unused_pool_owner.pool()->IsRunningSequenceOnCurrentThread(token1)); | 813 unused_pool->IsRunningSequenceOnCurrentThread(unsequenced_token)); |
| 805 EXPECT_FALSE( | |
| 806 unused_pool_owner.pool()->IsRunningSequenceOnCurrentThread(token2)); | |
| 807 EXPECT_FALSE(unused_pool_owner.pool()->IsRunningSequenceOnCurrentThread( | |
| 808 unsequenced_token)); | |
| 809 | 814 |
| 810 pool()->PostSequencedWorkerTask( | 815 pool()->PostSequencedWorkerTask( |
| 811 token1, FROM_HERE, base::Bind(&IsRunningOnCurrentThreadTask, token1, | 816 token1, FROM_HERE, |
| 812 token2, pool(), unused_pool_owner.pool())); | 817 base::Bind(&IsRunningOnCurrentThreadTask, |
| 818 token1, token2, pool(), unused_pool)); |
| 813 pool()->PostSequencedWorkerTask( | 819 pool()->PostSequencedWorkerTask( |
| 814 token2, FROM_HERE, | 820 token2, FROM_HERE, |
| 815 base::Bind(&IsRunningOnCurrentThreadTask, token2, unsequenced_token, | 821 base::Bind(&IsRunningOnCurrentThreadTask, |
| 816 pool(), unused_pool_owner.pool())); | 822 token2, unsequenced_token, pool(), unused_pool)); |
| 817 pool()->PostWorkerTask( | 823 pool()->PostWorkerTask( |
| 818 FROM_HERE, base::Bind(&IsRunningOnCurrentThreadTask, unsequenced_token, | 824 FROM_HERE, |
| 819 token1, pool(), unused_pool_owner.pool())); | 825 base::Bind(&IsRunningOnCurrentThreadTask, |
| 826 unsequenced_token, token1, pool(), unused_pool)); |
| 827 pool()->Shutdown(); |
| 828 unused_pool->Shutdown(); |
| 820 } | 829 } |
| 821 | 830 |
| 822 // Checks that tasks are destroyed in the right context during shutdown. If a | 831 // Checks that tasks are destroyed in the right context during shutdown. If a |
| 823 // task is destroyed while SequencedWorkerPool's global lock is held, | 832 // task is destroyed while SequencedWorkerPool's global lock is held, |
| 824 // SequencedWorkerPool might deadlock. | 833 // SequencedWorkerPool might deadlock. |
| 825 TEST_F(SequencedWorkerPoolTest, AvoidsDeadlockOnShutdown) { | 834 TEST_F(SequencedWorkerPoolTest, AvoidsDeadlockOnShutdown) { |
| 826 for (int i = 0; i < 4; ++i) { | 835 for (int i = 0; i < 4; ++i) { |
| 827 scoped_refptr<DestructionDeadlockChecker> checker( | 836 scoped_refptr<DestructionDeadlockChecker> checker( |
| 828 new DestructionDeadlockChecker(pool())); | 837 new DestructionDeadlockChecker(pool())); |
| 829 tracker()->PostRepostingTask(pool(), checker); | 838 tracker()->PostRepostingTask(pool(), checker); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 token2, FROM_HERE, | 940 token2, FROM_HERE, |
| 932 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), token2)); | 941 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), token2)); |
| 933 | 942 |
| 934 pool()->PostWorkerTask(FROM_HERE, | 943 pool()->PostWorkerTask(FROM_HERE, |
| 935 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), | 944 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), |
| 936 SequencedWorkerPool::SequenceToken())); | 945 SequencedWorkerPool::SequenceToken())); |
| 937 | 946 |
| 938 pool()->FlushForTesting(); | 947 pool()->FlushForTesting(); |
| 939 } | 948 } |
| 940 | 949 |
| 941 TEST_F(SequencedWorkerPoolTest, ShutsDownCleanWithContinueOnShutdown) { | 950 TEST(SequencedWorkerPoolRefPtrTest, ShutsDownCleanWithContinueOnShutdown) { |
| 951 MessageLoop loop; |
| 952 scoped_refptr<SequencedWorkerPool> pool(new SequencedWorkerPool(3, "Pool")); |
| 942 scoped_refptr<SequencedTaskRunner> task_runner = | 953 scoped_refptr<SequencedTaskRunner> task_runner = |
| 943 pool()->GetSequencedTaskRunnerWithShutdownBehavior( | 954 pool->GetSequencedTaskRunnerWithShutdownBehavior( |
| 944 pool()->GetSequenceToken(), | 955 pool->GetSequenceToken(), |
| 945 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); | 956 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| 946 | 957 |
| 947 // Upon test exit, should shut down without hanging. | 958 // Upon test exit, should shut down without hanging. |
| 948 pool()->Shutdown(); | 959 pool->Shutdown(); |
| 949 } | 960 } |
| 950 | 961 |
| 951 class SequencedWorkerPoolTaskRunnerTestDelegate { | 962 class SequencedWorkerPoolTaskRunnerTestDelegate { |
| 952 public: | 963 public: |
| 953 SequencedWorkerPoolTaskRunnerTestDelegate() {} | 964 SequencedWorkerPoolTaskRunnerTestDelegate() {} |
| 954 | 965 |
| 955 ~SequencedWorkerPoolTaskRunnerTestDelegate() {} | 966 ~SequencedWorkerPoolTaskRunnerTestDelegate() {} |
| 956 | 967 |
| 957 void StartTaskRunner() { | 968 void StartTaskRunner() { |
| 958 pool_owner_.reset( | 969 pool_owner_.reset( |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1067 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, | 1078 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, |
| 1068 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 1079 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
| 1069 INSTANTIATE_TYPED_TEST_CASE_P( | 1080 INSTANTIATE_TYPED_TEST_CASE_P( |
| 1070 SequencedWorkerPoolSequencedTaskRunner, | 1081 SequencedWorkerPoolSequencedTaskRunner, |
| 1071 SequencedTaskRunnerDelayedTest, | 1082 SequencedTaskRunnerDelayedTest, |
| 1072 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 1083 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
| 1073 | 1084 |
| 1074 } // namespace | 1085 } // namespace |
| 1075 | 1086 |
| 1076 } // namespace base | 1087 } // namespace base |
| OLD | NEW |