| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 60     cond_var_.Signal(); | 60     cond_var_.Signal(); | 
| 61   } | 61   } | 
| 62 | 62 | 
| 63  private: | 63  private: | 
| 64   base::Lock lock_; | 64   base::Lock lock_; | 
| 65   base::ConditionVariable cond_var_; | 65   base::ConditionVariable cond_var_; | 
| 66 | 66 | 
| 67   size_t unblock_counter_; | 67   size_t unblock_counter_; | 
| 68 }; | 68 }; | 
| 69 | 69 | 
|  | 70 class DestructionDeadlockChecker | 
|  | 71     : public base::RefCountedThreadSafe<DestructionDeadlockChecker> { | 
|  | 72  public: | 
|  | 73   DestructionDeadlockChecker(const scoped_refptr<SequencedWorkerPool>& pool) | 
|  | 74       : pool_(pool) {} | 
|  | 75 | 
|  | 76  protected: | 
|  | 77   virtual ~DestructionDeadlockChecker() { | 
|  | 78     // This method should not deadlock. | 
|  | 79     pool_->RunsTasksOnCurrentThread(); | 
|  | 80   } | 
|  | 81 | 
|  | 82  private: | 
|  | 83   scoped_refptr<SequencedWorkerPool> pool_; | 
|  | 84   friend class base::RefCountedThreadSafe<DestructionDeadlockChecker>; | 
|  | 85 }; | 
|  | 86 | 
| 70 class TestTracker : public base::RefCountedThreadSafe<TestTracker> { | 87 class TestTracker : public base::RefCountedThreadSafe<TestTracker> { | 
| 71  public: | 88  public: | 
| 72   TestTracker() | 89   TestTracker() | 
| 73       : lock_(), | 90       : lock_(), | 
| 74         cond_var_(&lock_), | 91         cond_var_(&lock_), | 
| 75         started_events_(0) { | 92         started_events_(0) { | 
| 76   } | 93   } | 
| 77 | 94 | 
| 78   // Each of these tasks appends the argument to the complete sequence vector | 95   // Each of these tasks appends the argument to the complete sequence vector | 
| 79   // so calling code can see what order they finished in. | 96   // so calling code can see what order they finished in. | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 110     EXPECT_EQ(expected_return_value, | 127     EXPECT_EQ(expected_return_value, | 
| 111               pool->PostWorkerTaskWithShutdownBehavior( | 128               pool->PostWorkerTaskWithShutdownBehavior( | 
| 112                   FROM_HERE, fast_task, | 129                   FROM_HERE, fast_task, | 
| 113                   SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | 130                   SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | 
| 114     pool->PostWorkerTaskWithShutdownBehavior( | 131     pool->PostWorkerTaskWithShutdownBehavior( | 
| 115         FROM_HERE, fast_task, | 132         FROM_HERE, fast_task, | 
| 116         SequencedWorkerPool::BLOCK_SHUTDOWN); | 133         SequencedWorkerPool::BLOCK_SHUTDOWN); | 
| 117     SignalWorkerDone(id); | 134     SignalWorkerDone(id); | 
| 118   } | 135   } | 
| 119 | 136 | 
|  | 137   // This task posts itself back onto the SequencedWorkerPool before it | 
|  | 138   // finishes running. Each instance of the task maintains a strong reference | 
|  | 139   // to a DestructionDeadlockChecker. The DestructionDeadlockChecker is only | 
|  | 140   // destroyed when the task is destroyed without being run, which only happens | 
|  | 141   // during destruction of the SequencedWorkerPool. | 
|  | 142   void PostRepostingTask( | 
|  | 143       const scoped_refptr<SequencedWorkerPool>& pool, | 
|  | 144       const scoped_refptr<DestructionDeadlockChecker>& checker) { | 
|  | 145     Closure reposting_task = | 
|  | 146         base::Bind(&TestTracker::PostRepostingTask, this, pool, checker); | 
|  | 147     pool->PostWorkerTaskWithShutdownBehavior( | 
|  | 148         FROM_HERE, reposting_task, SequencedWorkerPool::SKIP_ON_SHUTDOWN); | 
|  | 149   } | 
|  | 150 | 
| 120   // Waits until the given number of tasks have started executing. | 151   // Waits until the given number of tasks have started executing. | 
| 121   void WaitUntilTasksBlocked(size_t count) { | 152   void WaitUntilTasksBlocked(size_t count) { | 
| 122     { | 153     { | 
| 123       base::AutoLock lock(lock_); | 154       base::AutoLock lock(lock_); | 
| 124       while (started_events_ < count) | 155       while (started_events_ < count) | 
| 125         cond_var_.Wait(); | 156         cond_var_.Wait(); | 
| 126     } | 157     } | 
| 127     cond_var_.Signal(); | 158     cond_var_.Signal(); | 
| 128   } | 159   } | 
| 129 | 160 | 
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 742       base::Bind(&IsRunningOnCurrentThreadTask, | 773       base::Bind(&IsRunningOnCurrentThreadTask, | 
| 743                  token2, unsequenced_token, pool(), unused_pool)); | 774                  token2, unsequenced_token, pool(), unused_pool)); | 
| 744   pool()->PostWorkerTask( | 775   pool()->PostWorkerTask( | 
| 745       FROM_HERE, | 776       FROM_HERE, | 
| 746       base::Bind(&IsRunningOnCurrentThreadTask, | 777       base::Bind(&IsRunningOnCurrentThreadTask, | 
| 747                  unsequenced_token, token1, pool(), unused_pool)); | 778                  unsequenced_token, token1, pool(), unused_pool)); | 
| 748   pool()->Shutdown(); | 779   pool()->Shutdown(); | 
| 749   unused_pool->Shutdown(); | 780   unused_pool->Shutdown(); | 
| 750 } | 781 } | 
| 751 | 782 | 
|  | 783 // Checks that tasks are destroyed in the right context during shutdown. If a | 
|  | 784 // task is destroyed while SequencedWorkerPool's global lock is held, | 
|  | 785 // SequencedWorkerPool might deadlock. | 
|  | 786 TEST_F(SequencedWorkerPoolTest, AvoidsDeadlockOnShutdown) { | 
|  | 787   for (int i = 0; i < 4; ++i) { | 
|  | 788     scoped_refptr<DestructionDeadlockChecker> checker( | 
|  | 789         new DestructionDeadlockChecker(pool())); | 
|  | 790     tracker()->PostRepostingTask(pool(), checker); | 
|  | 791   } | 
|  | 792 | 
|  | 793   // Shutting down the pool should destroy the DestructionDeadlockCheckers, | 
|  | 794   // which in turn should not deadlock in their destructors. | 
|  | 795   pool()->Shutdown(); | 
|  | 796 } | 
|  | 797 | 
| 752 // Verify that FlushForTesting works as intended. | 798 // Verify that FlushForTesting works as intended. | 
| 753 TEST_F(SequencedWorkerPoolTest, FlushForTesting) { | 799 TEST_F(SequencedWorkerPoolTest, FlushForTesting) { | 
| 754   // Should be fine to call on a new instance. | 800   // Should be fine to call on a new instance. | 
| 755   pool()->FlushForTesting(); | 801   pool()->FlushForTesting(); | 
| 756 | 802 | 
| 757   // Queue up a bunch of work, including  a long delayed task and | 803   // Queue up a bunch of work, including  a long delayed task and | 
| 758   // a task that produces additional tasks as an artifact. | 804   // a task that produces additional tasks as an artifact. | 
| 759   pool()->PostDelayedWorkerTask( | 805   pool()->PostDelayedWorkerTask( | 
| 760       FROM_HERE, | 806       FROM_HERE, | 
| 761       base::Bind(&TestTracker::FastTask, tracker(), 0), | 807       base::Bind(&TestTracker::FastTask, tracker(), 0), | 
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 909     SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, | 955     SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, | 
| 910     SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 956     SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 
| 911 | 957 | 
| 912 INSTANTIATE_TYPED_TEST_CASE_P( | 958 INSTANTIATE_TYPED_TEST_CASE_P( | 
| 913     SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, | 959     SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, | 
| 914     SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 960     SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 
| 915 | 961 | 
| 916 }  // namespace | 962 }  // namespace | 
| 917 | 963 | 
| 918 }  // namespace base | 964 }  // namespace base | 
| OLD | NEW | 
|---|