| 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 { | 90 { |
| 91 base::AutoLock lock(lock_); | 91 base::AutoLock lock(lock_); |
| 92 started_events_++; | 92 started_events_++; |
| 93 } | 93 } |
| 94 cond_var_.Signal(); | 94 cond_var_.Signal(); |
| 95 | 95 |
| 96 blocker->Block(); | 96 blocker->Block(); |
| 97 SignalWorkerDone(id); | 97 SignalWorkerDone(id); |
| 98 } | 98 } |
| 99 | 99 |
| 100 void PostAdditionalTasks(int id, SequencedWorkerPool* pool) { | 100 void PostAdditionalTasks( |
| 101 int id, SequencedWorkerPool* pool, |
| 102 const bool* expected_return_values) { |
| 101 Closure fast_task = base::Bind(&TestTracker::FastTask, this, 100); | 103 Closure fast_task = base::Bind(&TestTracker::FastTask, this, 100); |
| 102 EXPECT_FALSE( | 104 EXPECT_EQ(expected_return_values[0], |
| 103 pool->PostWorkerTaskWithShutdownBehavior( | 105 pool->PostWorkerTaskWithShutdownBehavior( |
| 104 FROM_HERE, fast_task, | 106 FROM_HERE, fast_task, |
| 105 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); | 107 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
| 106 EXPECT_FALSE( | 108 EXPECT_EQ(expected_return_values[1], |
| 107 pool->PostWorkerTaskWithShutdownBehavior( | 109 pool->PostWorkerTaskWithShutdownBehavior( |
| 108 FROM_HERE, fast_task, | 110 FROM_HERE, fast_task, |
| 109 SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | 111 SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
| 110 pool->PostWorkerTaskWithShutdownBehavior( | 112 pool->PostWorkerTaskWithShutdownBehavior( |
| 111 FROM_HERE, fast_task, | 113 FROM_HERE, fast_task, |
| 112 SequencedWorkerPool::BLOCK_SHUTDOWN); | 114 SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 113 SignalWorkerDone(id); | 115 SignalWorkerDone(id); |
| 114 } | 116 } |
| 115 | 117 |
| 116 // Waits until the given number of tasks have started executing. | 118 // Waits until the given number of tasks have started executing. |
| 117 void WaitUntilTasksBlocked(size_t count) { | 119 void WaitUntilTasksBlocked(size_t count) { |
| 118 { | 120 { |
| 119 base::AutoLock lock(lock_); | 121 base::AutoLock lock(lock_); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 130 { | 132 { |
| 131 base::AutoLock lock(lock_); | 133 base::AutoLock lock(lock_); |
| 132 while (complete_sequence_.size() < num_tasks) | 134 while (complete_sequence_.size() < num_tasks) |
| 133 cond_var_.Wait(); | 135 cond_var_.Wait(); |
| 134 ret = complete_sequence_; | 136 ret = complete_sequence_; |
| 135 } | 137 } |
| 136 cond_var_.Signal(); | 138 cond_var_.Signal(); |
| 137 return ret; | 139 return ret; |
| 138 } | 140 } |
| 139 | 141 |
| 142 size_t GetTasksCompletedCount() { |
| 143 base::AutoLock lock(lock_); |
| 144 return complete_sequence_.size(); |
| 145 } |
| 146 |
| 140 void ClearCompleteSequence() { | 147 void ClearCompleteSequence() { |
| 141 base::AutoLock lock(lock_); | 148 base::AutoLock lock(lock_); |
| 142 complete_sequence_.clear(); | 149 complete_sequence_.clear(); |
| 143 started_events_ = 0; | 150 started_events_ = 0; |
| 144 } | 151 } |
| 145 | 152 |
| 146 private: | 153 private: |
| 147 friend class base::RefCountedThreadSafe<TestTracker>; | 154 friend class base::RefCountedThreadSafe<TestTracker>; |
| 148 ~TestTracker() {} | 155 ~TestTracker() {} |
| 149 | 156 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 for (int i = 0; i < kNumBlockTasks; ++i) { | 450 for (int i = 0; i < kNumBlockTasks; ++i) { |
| 444 EXPECT_TRUE(pool()->PostWorkerTask( | 451 EXPECT_TRUE(pool()->PostWorkerTask( |
| 445 FROM_HERE, | 452 FROM_HERE, |
| 446 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); | 453 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); |
| 447 } | 454 } |
| 448 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); | 455 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 449 | 456 |
| 450 // Queue up shutdown blocking tasks behind those which will attempt to post | 457 // Queue up shutdown blocking tasks behind those which will attempt to post |
| 451 // additional tasks when run, PostAdditionalTasks attemtps to post 3 | 458 // additional tasks when run, PostAdditionalTasks attemtps to post 3 |
| 452 // new FastTasks, one for each shutdown_behavior. | 459 // new FastTasks, one for each shutdown_behavior. |
| 460 const bool kExpectedReturnValues[] = {false, false}; |
| 453 const int kNumQueuedTasks = static_cast<int>(kNumWorkerThreads); | 461 const int kNumQueuedTasks = static_cast<int>(kNumWorkerThreads); |
| 454 for (int i = 0; i < kNumQueuedTasks; ++i) { | 462 for (int i = 0; i < kNumQueuedTasks; ++i) { |
| 455 EXPECT_TRUE(pool()->PostWorkerTaskWithShutdownBehavior( | 463 EXPECT_TRUE(pool()->PostWorkerTaskWithShutdownBehavior( |
| 456 FROM_HERE, | 464 FROM_HERE, |
| 457 base::Bind(&TestTracker::PostAdditionalTasks, tracker(), i, pool()), | 465 base::Bind(&TestTracker::PostAdditionalTasks, tracker(), i, pool(), |
| 466 kExpectedReturnValues), |
| 458 SequencedWorkerPool::BLOCK_SHUTDOWN)); | 467 SequencedWorkerPool::BLOCK_SHUTDOWN)); |
| 459 } | 468 } |
| 460 | 469 |
| 461 // Setup to open the floodgates from within Shutdown(). | 470 // Setup to open the floodgates from within Shutdown(). |
| 462 SetWillWaitForShutdownCallback( | 471 SetWillWaitForShutdownCallback( |
| 463 base::Bind(&EnsureTasksToCompleteCountAndUnblock, | 472 base::Bind(&EnsureTasksToCompleteCountAndUnblock, |
| 464 scoped_refptr<TestTracker>(tracker()), | 473 scoped_refptr<TestTracker>(tracker()), |
| 465 0, &blocker, kNumBlockTasks)); | 474 0, &blocker, kNumBlockTasks)); |
| 466 | 475 |
| 467 // Allow half of the additional blocking tasks thru. | 476 // Allow half of the additional blocking tasks thru. |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 base::Bind(&IsRunningOnCurrentThreadTask, | 688 base::Bind(&IsRunningOnCurrentThreadTask, |
| 680 token2, unsequenced_token, pool(), unused_pool)); | 689 token2, unsequenced_token, pool(), unused_pool)); |
| 681 pool()->PostWorkerTask( | 690 pool()->PostWorkerTask( |
| 682 FROM_HERE, | 691 FROM_HERE, |
| 683 base::Bind(&IsRunningOnCurrentThreadTask, | 692 base::Bind(&IsRunningOnCurrentThreadTask, |
| 684 unsequenced_token, token1, pool(), unused_pool)); | 693 unsequenced_token, token1, pool(), unused_pool)); |
| 685 pool()->Shutdown(); | 694 pool()->Shutdown(); |
| 686 unused_pool->Shutdown(); | 695 unused_pool->Shutdown(); |
| 687 } | 696 } |
| 688 | 697 |
| 698 // Verify that FlushForTesting works as intended. |
| 699 TEST_F(SequencedWorkerPoolTest, FlushForTesting) { |
| 700 // Should be fine to call on a new instance. |
| 701 pool()->FlushForTesting(); |
| 702 |
| 703 // Queue up a bunch of work, including work that produces additional |
| 704 // work as an artifact. |
| 705 pool()->PostDelayedWorkerTask( |
| 706 FROM_HERE, |
| 707 base::Bind(&TestTracker::FastTask, tracker(), 0), |
| 708 TimeDelta::FromMinutes(5)); |
| 709 pool()->PostWorkerTask(FROM_HERE, |
| 710 base::Bind(&TestTracker::SlowTask, tracker(), 0)); |
| 711 const size_t kNumFastTasks = 20; |
| 712 for (size_t i = 0; i < kNumFastTasks; i++) { |
| 713 pool()->PostWorkerTask(FROM_HERE, |
| 714 base::Bind(&TestTracker::FastTask, tracker(), 0)); |
| 715 } |
| 716 const bool kExpectedReturnValues[] = {true, true}; |
| 717 pool()->PostWorkerTask( |
| 718 FROM_HERE, |
| 719 base::Bind(&TestTracker::PostAdditionalTasks, tracker(), 0, pool(), |
| 720 kExpectedReturnValues)); |
| 721 EXPECT_FALSE(tracker()->HasOneRef()); |
| 722 pool()->FlushForTesting(); |
| 723 |
| 724 // We expect all except the delayed task to have been run. We verify all |
| 725 // closures have been deleted deleted by looking at the refcount of the |
| 726 // tracker. |
| 727 EXPECT_EQ(1 + kNumFastTasks + 1 + 3, tracker()->GetTasksCompletedCount()); |
| 728 EXPECT_TRUE(tracker()->HasOneRef()); |
| 729 |
| 730 // Should be fine to call on an idle instance with all threads created, and |
| 731 // spamming the method shouldn't deadlock or confuse the class. |
| 732 pool()->FlushForTesting(); |
| 733 pool()->FlushForTesting(); |
| 734 pool()->Shutdown(); |
| 735 } |
| 736 |
| 689 class SequencedWorkerPoolTaskRunnerTestDelegate { | 737 class SequencedWorkerPoolTaskRunnerTestDelegate { |
| 690 public: | 738 public: |
| 691 SequencedWorkerPoolTaskRunnerTestDelegate() {} | 739 SequencedWorkerPoolTaskRunnerTestDelegate() {} |
| 692 | 740 |
| 693 ~SequencedWorkerPoolTaskRunnerTestDelegate() {} | 741 ~SequencedWorkerPoolTaskRunnerTestDelegate() {} |
| 694 | 742 |
| 695 void StartTaskRunner() { | 743 void StartTaskRunner() { |
| 696 pool_owner_.reset( | 744 pool_owner_.reset( |
| 697 new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); | 745 new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); |
| 698 } | 746 } |
| 699 | 747 |
| 700 scoped_refptr<SequencedWorkerPool> GetTaskRunner() { | 748 scoped_refptr<SequencedWorkerPool> GetTaskRunner() { |
| 701 return pool_owner_->pool(); | 749 return pool_owner_->pool(); |
| 702 } | 750 } |
| 703 | 751 |
| 704 void StopTaskRunner() { | 752 void StopTaskRunner() { |
| 705 // Make sure all tasks (including delayed ones) are run before shutting | 753 // Make sure all tasks are run before shutting down. Delayed tasks are |
| 706 // down. | 754 // not run, they're simply deleted. |
| 707 pool_owner_->pool()->FlushForTesting(); | 755 pool_owner_->pool()->FlushForTesting(); |
| 708 pool_owner_->pool()->Shutdown(); | 756 pool_owner_->pool()->Shutdown(); |
| 709 // Don't reset |pool_owner_| here, as the test may still hold a | 757 // Don't reset |pool_owner_| here, as the test may still hold a |
| 710 // reference to the pool. | 758 // reference to the pool. |
| 711 } | 759 } |
| 712 | 760 |
| 713 bool TaskRunnerHandlesNonZeroDelays() const { | 761 bool TaskRunnerHandlesNonZeroDelays() const { |
| 714 return true; | 762 return true; |
| 715 } | 763 } |
| 716 | 764 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 735 new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); | 783 new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); |
| 736 task_runner_ = pool_owner_->pool()->GetTaskRunnerWithShutdownBehavior( | 784 task_runner_ = pool_owner_->pool()->GetTaskRunnerWithShutdownBehavior( |
| 737 SequencedWorkerPool::BLOCK_SHUTDOWN); | 785 SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 738 } | 786 } |
| 739 | 787 |
| 740 scoped_refptr<TaskRunner> GetTaskRunner() { | 788 scoped_refptr<TaskRunner> GetTaskRunner() { |
| 741 return task_runner_; | 789 return task_runner_; |
| 742 } | 790 } |
| 743 | 791 |
| 744 void StopTaskRunner() { | 792 void StopTaskRunner() { |
| 745 // Make sure all tasks (including delayed ones) are run before shutting | 793 // Make sure all tasks are run before shutting down. Delayed tasks are |
| 746 // down. | 794 // not run, they're simply deleted. |
| 747 pool_owner_->pool()->FlushForTesting(); | 795 pool_owner_->pool()->FlushForTesting(); |
| 748 pool_owner_->pool()->Shutdown(); | 796 pool_owner_->pool()->Shutdown(); |
| 749 // Don't reset |pool_owner_| here, as the test may still hold a | 797 // Don't reset |pool_owner_| here, as the test may still hold a |
| 750 // reference to the pool. | 798 // reference to the pool. |
| 751 } | 799 } |
| 752 | 800 |
| 753 bool TaskRunnerHandlesNonZeroDelays() const { | 801 bool TaskRunnerHandlesNonZeroDelays() const { |
| 754 return true; | 802 return true; |
| 755 } | 803 } |
| 756 | 804 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 776 10, "SequencedWorkerPoolSequencedTaskRunnerTest")); | 824 10, "SequencedWorkerPoolSequencedTaskRunnerTest")); |
| 777 task_runner_ = pool_owner_->pool()->GetSequencedTaskRunner( | 825 task_runner_ = pool_owner_->pool()->GetSequencedTaskRunner( |
| 778 pool_owner_->pool()->GetSequenceToken()); | 826 pool_owner_->pool()->GetSequenceToken()); |
| 779 } | 827 } |
| 780 | 828 |
| 781 scoped_refptr<SequencedTaskRunner> GetTaskRunner() { | 829 scoped_refptr<SequencedTaskRunner> GetTaskRunner() { |
| 782 return task_runner_; | 830 return task_runner_; |
| 783 } | 831 } |
| 784 | 832 |
| 785 void StopTaskRunner() { | 833 void StopTaskRunner() { |
| 786 // Make sure all tasks (including delayed ones) are run before shutting | 834 // Make sure all tasks are run before shutting down. Delayed tasks are |
| 787 // down. | 835 // not run, they're simply deleted. |
| 788 pool_owner_->pool()->FlushForTesting(); | 836 pool_owner_->pool()->FlushForTesting(); |
| 789 pool_owner_->pool()->Shutdown(); | 837 pool_owner_->pool()->Shutdown(); |
| 790 // Don't reset |pool_owner_| here, as the test may still hold a | 838 // Don't reset |pool_owner_| here, as the test may still hold a |
| 791 // reference to the pool. | 839 // reference to the pool. |
| 792 } | 840 } |
| 793 | 841 |
| 794 bool TaskRunnerHandlesNonZeroDelays() const { | 842 bool TaskRunnerHandlesNonZeroDelays() const { |
| 795 return true; | 843 return true; |
| 796 } | 844 } |
| 797 | 845 |
| 798 private: | 846 private: |
| 799 MessageLoop message_loop_; | 847 MessageLoop message_loop_; |
| 800 scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; | 848 scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; |
| 801 scoped_refptr<SequencedTaskRunner> task_runner_; | 849 scoped_refptr<SequencedTaskRunner> task_runner_; |
| 802 }; | 850 }; |
| 803 | 851 |
| 804 INSTANTIATE_TYPED_TEST_CASE_P( | 852 INSTANTIATE_TYPED_TEST_CASE_P( |
| 805 SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, | 853 SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, |
| 806 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 854 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
| 807 | 855 |
| 808 INSTANTIATE_TYPED_TEST_CASE_P( | 856 INSTANTIATE_TYPED_TEST_CASE_P( |
| 809 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, | 857 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, |
| 810 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 858 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
| 811 | 859 |
| 812 } // namespace | 860 } // namespace |
| 813 | 861 |
| 814 } // namespace base | 862 } // namespace base |
| OLD | NEW |