| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/worker_pool_posix.h" | 5 #include "base/threading/worker_pool_posix.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/lock.h" | |
| 10 #include "base/synchronization/condition_variable.h" | 9 #include "base/synchronization/condition_variable.h" |
| 10 #include "base/synchronization/lock.h" |
| 11 #include "base/task.h" | 11 #include "base/task.h" |
| 12 #include "base/threading/platform_thread.h" | 12 #include "base/threading/platform_thread.h" |
| 13 #include "base/synchronization/waitable_event.h" | 13 #include "base/synchronization/waitable_event.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 15 |
| 16 namespace base { | 16 namespace base { |
| 17 | 17 |
| 18 // Peer class to provide passthrough access to PosixDynamicThreadPool internals. | 18 // Peer class to provide passthrough access to PosixDynamicThreadPool internals. |
| 19 class PosixDynamicThreadPool::PosixDynamicThreadPoolPeer { | 19 class PosixDynamicThreadPool::PosixDynamicThreadPoolPeer { |
| 20 public: | 20 public: |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 int* counter, | 54 int* counter, |
| 55 Lock* unique_threads_lock, | 55 Lock* unique_threads_lock, |
| 56 std::set<PlatformThreadId>* unique_threads) | 56 std::set<PlatformThreadId>* unique_threads) |
| 57 : counter_lock_(counter_lock), | 57 : counter_lock_(counter_lock), |
| 58 unique_threads_lock_(unique_threads_lock), | 58 unique_threads_lock_(unique_threads_lock), |
| 59 unique_threads_(unique_threads), | 59 unique_threads_(unique_threads), |
| 60 counter_(counter) {} | 60 counter_(counter) {} |
| 61 | 61 |
| 62 virtual void Run() { | 62 virtual void Run() { |
| 63 AddSelfToUniqueThreadSet(); | 63 AddSelfToUniqueThreadSet(); |
| 64 AutoLock locked(*counter_lock_); | 64 base::AutoLock locked(*counter_lock_); |
| 65 (*counter_)++; | 65 (*counter_)++; |
| 66 } | 66 } |
| 67 | 67 |
| 68 void AddSelfToUniqueThreadSet() { | 68 void AddSelfToUniqueThreadSet() { |
| 69 AutoLock locked(*unique_threads_lock_); | 69 base::AutoLock locked(*unique_threads_lock_); |
| 70 unique_threads_->insert(PlatformThread::CurrentId()); | 70 unique_threads_->insert(PlatformThread::CurrentId()); |
| 71 } | 71 } |
| 72 | 72 |
| 73 private: | 73 private: |
| 74 Lock* counter_lock_; | 74 Lock* counter_lock_; |
| 75 Lock* unique_threads_lock_; | 75 Lock* unique_threads_lock_; |
| 76 std::set<PlatformThreadId>* unique_threads_; | 76 std::set<PlatformThreadId>* unique_threads_; |
| 77 int* counter_; | 77 int* counter_; |
| 78 | 78 |
| 79 DISALLOW_COPY_AND_ASSIGN(IncrementingTask); | 79 DISALLOW_COPY_AND_ASSIGN(IncrementingTask); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 93 base::WaitableEvent* start) | 93 base::WaitableEvent* start) |
| 94 : incrementer_( | 94 : incrementer_( |
| 95 counter_lock, counter, unique_threads_lock, unique_threads), | 95 counter_lock, counter, unique_threads_lock, unique_threads), |
| 96 num_waiting_to_start_lock_(num_waiting_to_start_lock), | 96 num_waiting_to_start_lock_(num_waiting_to_start_lock), |
| 97 num_waiting_to_start_(num_waiting_to_start), | 97 num_waiting_to_start_(num_waiting_to_start), |
| 98 num_waiting_to_start_cv_(num_waiting_to_start_cv), | 98 num_waiting_to_start_cv_(num_waiting_to_start_cv), |
| 99 start_(start) {} | 99 start_(start) {} |
| 100 | 100 |
| 101 virtual void Run() { | 101 virtual void Run() { |
| 102 { | 102 { |
| 103 AutoLock num_waiting_to_start_locked(*num_waiting_to_start_lock_); | 103 base::AutoLock num_waiting_to_start_locked(*num_waiting_to_start_lock_); |
| 104 (*num_waiting_to_start_)++; | 104 (*num_waiting_to_start_)++; |
| 105 } | 105 } |
| 106 num_waiting_to_start_cv_->Signal(); | 106 num_waiting_to_start_cv_->Signal(); |
| 107 CHECK(start_->Wait()); | 107 CHECK(start_->Wait()); |
| 108 incrementer_.Run(); | 108 incrementer_.Run(); |
| 109 } | 109 } |
| 110 | 110 |
| 111 private: | 111 private: |
| 112 IncrementingTask incrementer_; | 112 IncrementingTask incrementer_; |
| 113 Lock* num_waiting_to_start_lock_; | 113 Lock* num_waiting_to_start_lock_; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 131 virtual void SetUp() { | 131 virtual void SetUp() { |
| 132 peer_.set_num_idle_threads_cv(new ConditionVariable(peer_.lock())); | 132 peer_.set_num_idle_threads_cv(new ConditionVariable(peer_.lock())); |
| 133 } | 133 } |
| 134 | 134 |
| 135 virtual void TearDown() { | 135 virtual void TearDown() { |
| 136 // Wake up the idle threads so they can terminate. | 136 // Wake up the idle threads so they can terminate. |
| 137 if (pool_.get()) pool_->Terminate(); | 137 if (pool_.get()) pool_->Terminate(); |
| 138 } | 138 } |
| 139 | 139 |
| 140 void WaitForTasksToStart(int num_tasks) { | 140 void WaitForTasksToStart(int num_tasks) { |
| 141 AutoLock num_waiting_to_start_locked(num_waiting_to_start_lock_); | 141 base::AutoLock num_waiting_to_start_locked(num_waiting_to_start_lock_); |
| 142 while (num_waiting_to_start_ < num_tasks) { | 142 while (num_waiting_to_start_ < num_tasks) { |
| 143 num_waiting_to_start_cv_.Wait(); | 143 num_waiting_to_start_cv_.Wait(); |
| 144 } | 144 } |
| 145 } | 145 } |
| 146 | 146 |
| 147 void WaitForIdleThreads(int num_idle_threads) { | 147 void WaitForIdleThreads(int num_idle_threads) { |
| 148 AutoLock pool_locked(*peer_.lock()); | 148 base::AutoLock pool_locked(*peer_.lock()); |
| 149 while (peer_.num_idle_threads() < num_idle_threads) { | 149 while (peer_.num_idle_threads() < num_idle_threads) { |
| 150 peer_.num_idle_threads_cv()->Wait(); | 150 peer_.num_idle_threads_cv()->Wait(); |
| 151 } | 151 } |
| 152 } | 152 } |
| 153 | 153 |
| 154 Task* CreateNewIncrementingTask() { | 154 Task* CreateNewIncrementingTask() { |
| 155 return new IncrementingTask(&counter_lock_, &counter_, | 155 return new IncrementingTask(&counter_lock_, &counter_, |
| 156 &unique_threads_lock_, &unique_threads_); | 156 &unique_threads_lock_, &unique_threads_); |
| 157 } | 157 } |
| 158 | 158 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 WaitForTasksToStart(2); | 242 WaitForTasksToStart(2); |
| 243 start_.Signal(); | 243 start_.Signal(); |
| 244 WaitForIdleThreads(2); | 244 WaitForIdleThreads(2); |
| 245 | 245 |
| 246 EXPECT_EQ(3, counter_); | 246 EXPECT_EQ(3, counter_); |
| 247 EXPECT_EQ(2, peer_.num_idle_threads()); | 247 EXPECT_EQ(2, peer_.num_idle_threads()); |
| 248 EXPECT_EQ(2U, unique_threads_.size()); | 248 EXPECT_EQ(2U, unique_threads_.size()); |
| 249 | 249 |
| 250 // Wake up all idle threads so they can exit. | 250 // Wake up all idle threads so they can exit. |
| 251 { | 251 { |
| 252 AutoLock locked(*peer_.lock()); | 252 base::AutoLock locked(*peer_.lock()); |
| 253 while (peer_.num_idle_threads() > 0) { | 253 while (peer_.num_idle_threads() > 0) { |
| 254 peer_.tasks_available_cv()->Signal(); | 254 peer_.tasks_available_cv()->Signal(); |
| 255 peer_.num_idle_threads_cv()->Wait(); | 255 peer_.num_idle_threads_cv()->Wait(); |
| 256 } | 256 } |
| 257 } | 257 } |
| 258 | 258 |
| 259 // Add another non blocking task. There are no threads to reuse. | 259 // Add another non blocking task. There are no threads to reuse. |
| 260 pool_->PostTask(CreateNewIncrementingTask()); | 260 pool_->PostTask(CreateNewIncrementingTask()); |
| 261 WaitForIdleThreads(1); | 261 WaitForIdleThreads(1); |
| 262 | 262 |
| 263 EXPECT_EQ(3U, unique_threads_.size()); | 263 EXPECT_EQ(3U, unique_threads_.size()); |
| 264 EXPECT_EQ(1, peer_.num_idle_threads()); | 264 EXPECT_EQ(1, peer_.num_idle_threads()); |
| 265 EXPECT_EQ(4, counter_); | 265 EXPECT_EQ(4, counter_); |
| 266 } | 266 } |
| 267 | 267 |
| 268 } // namespace base | 268 } // namespace base |
| OLD | NEW |