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 <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 // SequencedWorkerPool from one test doesn't outlive its test and | 150 // SequencedWorkerPool from one test doesn't outlive its test and |
151 // cause strange races with other tests that touch global stuff (like | 151 // cause strange races with other tests that touch global stuff (like |
152 // histograms and logging). However, this requires that nothing else | 152 // histograms and logging). However, this requires that nothing else |
153 // on this thread holds a ref to the pool when the | 153 // on this thread holds a ref to the pool when the |
154 // SequencedWorkerPoolOwner is destroyed. | 154 // SequencedWorkerPoolOwner is destroyed. |
155 class SequencedWorkerPoolOwner : public SequencedWorkerPool::TestingObserver { | 155 class SequencedWorkerPoolOwner : public SequencedWorkerPool::TestingObserver { |
156 public: | 156 public: |
157 SequencedWorkerPoolOwner(size_t max_threads, | 157 SequencedWorkerPoolOwner(size_t max_threads, |
158 const std::string& thread_name_prefix) | 158 const std::string& thread_name_prefix) |
159 : constructor_message_loop_(MessageLoop::current()), | 159 : constructor_message_loop_(MessageLoop::current()), |
160 pool_(new SequencedWorkerPool(max_threads, thread_name_prefix)) { | 160 pool_(new SequencedWorkerPool( |
161 pool_->SetTestingObserver(this); | 161 max_threads, thread_name_prefix, |
162 } | 162 ALLOW_THIS_IN_INITIALIZER_LIST(this))), |
| 163 has_work_call_count_(0) {} |
163 | 164 |
164 virtual ~SequencedWorkerPoolOwner() { | 165 virtual ~SequencedWorkerPoolOwner() { |
165 pool_ = NULL; | 166 pool_ = NULL; |
166 MessageLoop::current()->Run(); | 167 MessageLoop::current()->Run(); |
167 } | 168 } |
168 | 169 |
169 // Don't change the return pool's testing observer. | 170 // Don't change the return pool's testing observer. |
170 const scoped_refptr<SequencedWorkerPool>& pool() { | 171 const scoped_refptr<SequencedWorkerPool>& pool() { |
171 return pool_; | 172 return pool_; |
172 } | 173 } |
173 | 174 |
174 // The given callback will be called on WillWaitForShutdown(). | 175 // The given callback will be called on WillWaitForShutdown(). |
175 void SetWillWaitForShutdownCallback(const Closure& callback) { | 176 void SetWillWaitForShutdownCallback(const Closure& callback) { |
176 will_wait_for_shutdown_callback_ = callback; | 177 will_wait_for_shutdown_callback_ = callback; |
177 } | 178 } |
178 | 179 |
| 180 int has_work_call_count() const { |
| 181 AutoLock lock(has_work_lock_); |
| 182 return has_work_call_count_; |
| 183 } |
| 184 |
179 private: | 185 private: |
180 // SequencedWorkerPool::TestingObserver implementation. | 186 // SequencedWorkerPool::TestingObserver implementation. |
| 187 virtual void OnHasWork() OVERRIDE { |
| 188 AutoLock lock(has_work_lock_); |
| 189 ++has_work_call_count_; |
| 190 } |
| 191 |
181 virtual void WillWaitForShutdown() OVERRIDE { | 192 virtual void WillWaitForShutdown() OVERRIDE { |
182 if (!will_wait_for_shutdown_callback_.is_null()) { | 193 if (!will_wait_for_shutdown_callback_.is_null()) { |
183 will_wait_for_shutdown_callback_.Run(); | 194 will_wait_for_shutdown_callback_.Run(); |
184 } | 195 } |
185 } | 196 } |
186 | 197 |
187 virtual void OnDestruct() OVERRIDE { | 198 virtual void OnDestruct() OVERRIDE { |
188 constructor_message_loop_->PostTask( | 199 constructor_message_loop_->PostTask( |
189 FROM_HERE, | 200 FROM_HERE, |
190 constructor_message_loop_->QuitClosure()); | 201 constructor_message_loop_->QuitClosure()); |
191 } | 202 } |
192 | 203 |
193 MessageLoop* const constructor_message_loop_; | 204 MessageLoop* const constructor_message_loop_; |
194 scoped_refptr<SequencedWorkerPool> pool_; | 205 scoped_refptr<SequencedWorkerPool> pool_; |
195 Closure will_wait_for_shutdown_callback_; | 206 Closure will_wait_for_shutdown_callback_; |
196 | 207 |
| 208 mutable Lock has_work_lock_; |
| 209 int has_work_call_count_; |
| 210 |
197 DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPoolOwner); | 211 DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPoolOwner); |
198 }; | 212 }; |
199 | 213 |
200 class SequencedWorkerPoolTest : public testing::Test { | 214 class SequencedWorkerPoolTest : public testing::Test { |
201 public: | 215 public: |
202 SequencedWorkerPoolTest() | 216 SequencedWorkerPoolTest() |
203 : pool_owner_(kNumWorkerThreads, "test"), | 217 : pool_owner_(kNumWorkerThreads, "test"), |
204 tracker_(new TestTracker) {} | 218 tracker_(new TestTracker) {} |
205 | 219 |
206 ~SequencedWorkerPoolTest() {} | 220 ~SequencedWorkerPoolTest() {} |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); | 260 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
247 | 261 |
248 // Now wake them up and wait until they're done. | 262 // Now wake them up and wait until they're done. |
249 blocker.Unblock(kNumWorkerThreads); | 263 blocker.Unblock(kNumWorkerThreads); |
250 tracker()->WaitUntilTasksComplete(kNumWorkerThreads); | 264 tracker()->WaitUntilTasksComplete(kNumWorkerThreads); |
251 | 265 |
252 // Clean up the task IDs we added. | 266 // Clean up the task IDs we added. |
253 tracker()->ClearCompleteSequence(); | 267 tracker()->ClearCompleteSequence(); |
254 } | 268 } |
255 | 269 |
| 270 int has_work_call_count() const { |
| 271 return pool_owner_.has_work_call_count(); |
| 272 } |
| 273 |
256 private: | 274 private: |
257 MessageLoop message_loop_; | 275 MessageLoop message_loop_; |
258 SequencedWorkerPoolOwner pool_owner_; | 276 SequencedWorkerPoolOwner pool_owner_; |
259 const scoped_refptr<TestTracker> tracker_; | 277 const scoped_refptr<TestTracker> tracker_; |
260 }; | 278 }; |
261 | 279 |
262 // Checks that the given number of entries are in the tasks to complete of | 280 // Checks that the given number of entries are in the tasks to complete of |
263 // the given tracker, and then signals the given event the given number of | 281 // the given tracker, and then signals the given event the given number of |
264 // times. This is used to wakt up blocked background threads before blocking | 282 // times. This is used to wakt up blocked background threads before blocking |
265 // on shutdown. | 283 // on shutdown. |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 blocker.Unblock(1); | 496 blocker.Unblock(1); |
479 std::vector<int> result = tracker()->WaitUntilTasksComplete(1); | 497 std::vector<int> result = tracker()->WaitUntilTasksComplete(1); |
480 EXPECT_EQ(1u, result.size()); | 498 EXPECT_EQ(1u, result.size()); |
481 } | 499 } |
482 | 500 |
483 // Ensure all worker threads are created, and then trigger a spurious | 501 // Ensure all worker threads are created, and then trigger a spurious |
484 // work signal. This shouldn't cause any other work signals to be | 502 // work signal. This shouldn't cause any other work signals to be |
485 // triggered. This is a regression test for http://crbug.com/117469. | 503 // triggered. This is a regression test for http://crbug.com/117469. |
486 TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) { | 504 TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) { |
487 EnsureAllWorkersCreated(); | 505 EnsureAllWorkersCreated(); |
488 int old_work_signal_count = pool()->GetWorkSignalCountForTesting(); | 506 int old_has_work_call_count = has_work_call_count(); |
489 pool()->TriggerSpuriousWorkSignalForTesting(); | 507 pool()->SignalHasWorkForTesting(); |
490 // This is inherently racy, but can only produce false positives. | 508 // This is inherently racy, but can only produce false positives. |
491 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | 509 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
492 EXPECT_EQ(old_work_signal_count + 1, pool()->GetWorkSignalCountForTesting()); | 510 EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); |
493 } | 511 } |
494 | 512 |
495 class SequencedWorkerPoolTaskRunnerTestDelegate { | 513 class SequencedWorkerPoolTaskRunnerTestDelegate { |
496 public: | 514 public: |
497 SequencedWorkerPoolTaskRunnerTestDelegate() {} | 515 SequencedWorkerPoolTaskRunnerTestDelegate() {} |
498 | 516 |
499 ~SequencedWorkerPoolTaskRunnerTestDelegate() {} | 517 ~SequencedWorkerPoolTaskRunnerTestDelegate() {} |
500 | 518 |
501 void StartTaskRunner() { | 519 void StartTaskRunner() { |
502 pool_owner_.reset( | 520 pool_owner_.reset( |
(...skipping 21 matching lines...) Expand all Loading... |
524 scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; | 542 scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; |
525 }; | 543 }; |
526 | 544 |
527 INSTANTIATE_TYPED_TEST_CASE_P( | 545 INSTANTIATE_TYPED_TEST_CASE_P( |
528 SequencedWorkerPool, TaskRunnerTest, | 546 SequencedWorkerPool, TaskRunnerTest, |
529 SequencedWorkerPoolTaskRunnerTestDelegate); | 547 SequencedWorkerPoolTaskRunnerTestDelegate); |
530 | 548 |
531 } // namespace | 549 } // namespace |
532 | 550 |
533 } // namespace base | 551 } // namespace base |
OLD | NEW |