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 |