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 |