| 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 |