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 |