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