| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 // Multi-threaded tests of ConditionVariable class. | 5 // Multi-threaded tests of ConditionVariable class. |
| 6 | 6 |
| 7 #include <time.h> | 7 #include <time.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/condition_variable.h" | 11 #include "base/condition_variable.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/platform_test.h" | 13 #include "base/platform_test.h" |
| 14 #include "base/platform_thread.h" | 14 #include "base/platform_thread.h" |
| 15 #include "base/scoped_ptr.h" | 15 #include "base/scoped_ptr.h" |
| 16 #include "base/spin_wait.h" | 16 #include "base/spin_wait.h" |
| 17 #include "base/thread_collision_warner.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 //------------------------------------------------------------------------------ | 21 //------------------------------------------------------------------------------ |
| 21 // Define our test class, with several common variables. | 22 // Define our test class, with several common variables. |
| 22 //------------------------------------------------------------------------------ | 23 //------------------------------------------------------------------------------ |
| 23 | 24 |
| 24 class ConditionVariableTest : public PlatformTest { | 25 class ConditionVariableTest : public PlatformTest { |
| 25 public: | 26 public: |
| 26 const TimeDelta kZeroMs; | 27 const TimeDelta kZeroMs; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 bool EveryIdWasAllocated() const; // Indicates that all IDs were handed out. | 70 bool EveryIdWasAllocated() const; // Indicates that all IDs were handed out. |
| 70 TimeDelta GetAnAssignment(int thread_id); // Get a work task duration. | 71 TimeDelta GetAnAssignment(int thread_id); // Get a work task duration. |
| 71 void WorkIsCompleted(int thread_id); | 72 void WorkIsCompleted(int thread_id); |
| 72 | 73 |
| 73 int task_count() const; | 74 int task_count() const; |
| 74 bool allow_help_requests() const; // Workers can signal more workers. | 75 bool allow_help_requests() const; // Workers can signal more workers. |
| 75 bool shutdown() const; // Check if shutdown has been requested. | 76 bool shutdown() const; // Check if shutdown has been requested. |
| 76 int shutdown_task_count() const; | 77 int shutdown_task_count() const; |
| 77 | 78 |
| 78 void thread_shutting_down(); | 79 void thread_shutting_down(); |
| 80 |
| 81 //---------------------------------------------------------------------------- |
| 82 // Worker threads can call them but not needed to acquire a lock |
| 79 Lock* lock(); | 83 Lock* lock(); |
| 80 | 84 |
| 81 ConditionVariable* work_is_available(); | 85 ConditionVariable* work_is_available(); |
| 82 ConditionVariable* all_threads_have_ids(); | 86 ConditionVariable* all_threads_have_ids(); |
| 83 ConditionVariable* no_more_tasks(); | 87 ConditionVariable* no_more_tasks(); |
| 84 | 88 |
| 85 //---------------------------------------------------------------------------- | 89 //---------------------------------------------------------------------------- |
| 86 // The rest of the methods are for use by the controlling master thread (the | 90 // The rest of the methods are for use by the controlling master thread (the |
| 87 // test case code). | 91 // test case code). |
| 88 void ResetHistory(); | 92 void ResetHistory(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 110 const int thread_count_; | 114 const int thread_count_; |
| 111 scoped_array<PlatformThreadHandle> thread_handles_; | 115 scoped_array<PlatformThreadHandle> thread_handles_; |
| 112 std::vector<int> assignment_history_; // Number of assignment per worker. | 116 std::vector<int> assignment_history_; // Number of assignment per worker. |
| 113 std::vector<int> completion_history_; // Number of completions per worker. | 117 std::vector<int> completion_history_; // Number of completions per worker. |
| 114 int thread_started_counter_; // Used to issue unique id to workers. | 118 int thread_started_counter_; // Used to issue unique id to workers. |
| 115 int shutdown_task_count_; // Number of tasks told to shutdown | 119 int shutdown_task_count_; // Number of tasks told to shutdown |
| 116 int task_count_; // Number of assignment tasks waiting to be processed. | 120 int task_count_; // Number of assignment tasks waiting to be processed. |
| 117 TimeDelta worker_delay_; // Time each task takes to complete. | 121 TimeDelta worker_delay_; // Time each task takes to complete. |
| 118 bool allow_help_requests_; // Workers can signal more workers. | 122 bool allow_help_requests_; // Workers can signal more workers. |
| 119 bool shutdown_; // Set when threads need to terminate. | 123 bool shutdown_; // Set when threads need to terminate. |
| 124 |
| 125 D_DEFINE_CRITICAL_SECTION(locked_methods_); |
| 120 }; | 126 }; |
| 121 | 127 |
| 122 //------------------------------------------------------------------------------ | 128 //------------------------------------------------------------------------------ |
| 123 // The next section contains the actual tests. | 129 // The next section contains the actual tests. |
| 124 //------------------------------------------------------------------------------ | 130 //------------------------------------------------------------------------------ |
| 125 | 131 |
| 126 TEST_F(ConditionVariableTest, StartupShutdownTest) { | 132 TEST_F(ConditionVariableTest, StartupShutdownTest) { |
| 127 Lock lock; | 133 Lock lock; |
| 128 | 134 |
| 129 // First try trivial startup/shutdown. | 135 // First try trivial startup/shutdown. |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 SetShutdown(); | 473 SetShutdown(); |
| 468 } | 474 } |
| 469 work_is_available_.Broadcast(); // Tell them all to terminate. | 475 work_is_available_.Broadcast(); // Tell them all to terminate. |
| 470 | 476 |
| 471 for (int i = 0; i < thread_count_; ++i) { | 477 for (int i = 0; i < thread_count_; ++i) { |
| 472 PlatformThread::Join(thread_handles_[i]); | 478 PlatformThread::Join(thread_handles_[i]); |
| 473 } | 479 } |
| 474 } | 480 } |
| 475 | 481 |
| 476 int WorkQueue::GetThreadId() { | 482 int WorkQueue::GetThreadId() { |
| 483 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 477 DCHECK(!EveryIdWasAllocated()); | 484 DCHECK(!EveryIdWasAllocated()); |
| 478 return thread_started_counter_++; // Give out Unique IDs. | 485 return thread_started_counter_++; // Give out Unique IDs. |
| 479 } | 486 } |
| 480 | 487 |
| 481 bool WorkQueue::EveryIdWasAllocated() const { | 488 bool WorkQueue::EveryIdWasAllocated() const { |
| 489 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 482 return thread_count_ == thread_started_counter_; | 490 return thread_count_ == thread_started_counter_; |
| 483 } | 491 } |
| 484 | 492 |
| 485 TimeDelta WorkQueue::GetAnAssignment(int thread_id) { | 493 TimeDelta WorkQueue::GetAnAssignment(int thread_id) { |
| 494 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 486 DCHECK_LT(0, task_count_); | 495 DCHECK_LT(0, task_count_); |
| 487 assignment_history_[thread_id]++; | 496 assignment_history_[thread_id]++; |
| 488 if (0 == --task_count_) { | 497 if (0 == --task_count_) { |
| 489 no_more_tasks_.Signal(); | 498 no_more_tasks_.Signal(); |
| 490 } | 499 } |
| 491 return worker_delay_; | 500 return worker_delay_; |
| 492 } | 501 } |
| 493 | 502 |
| 494 void WorkQueue::WorkIsCompleted(int thread_id) { | 503 void WorkQueue::WorkIsCompleted(int thread_id) { |
| 504 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 495 completion_history_[thread_id]++; | 505 completion_history_[thread_id]++; |
| 496 } | 506 } |
| 497 | 507 |
| 498 int WorkQueue::task_count() const { | 508 int WorkQueue::task_count() const { |
| 509 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 499 return task_count_; | 510 return task_count_; |
| 500 } | 511 } |
| 501 | 512 |
| 502 bool WorkQueue::allow_help_requests() const { | 513 bool WorkQueue::allow_help_requests() const { |
| 514 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 503 return allow_help_requests_; | 515 return allow_help_requests_; |
| 504 } | 516 } |
| 505 | 517 |
| 506 bool WorkQueue::shutdown() const { | 518 bool WorkQueue::shutdown() const { |
| 519 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 507 return shutdown_; | 520 return shutdown_; |
| 508 } | 521 } |
| 509 | 522 |
| 510 int WorkQueue::shutdown_task_count() const { | 523 int WorkQueue::shutdown_task_count() const { |
| 524 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 511 return shutdown_task_count_; | 525 return shutdown_task_count_; |
| 512 } | 526 } |
| 513 | 527 |
| 514 void WorkQueue::thread_shutting_down() { | 528 void WorkQueue::thread_shutting_down() { |
| 529 D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(locked_methods_); |
| 515 shutdown_task_count_++; | 530 shutdown_task_count_++; |
| 516 } | 531 } |
| 517 | 532 |
| 518 Lock* WorkQueue::lock() { | 533 Lock* WorkQueue::lock() { |
| 519 return &lock_; | 534 return &lock_; |
| 520 } | 535 } |
| 521 | 536 |
| 522 ConditionVariable* WorkQueue::work_is_available() { | 537 ConditionVariable* WorkQueue::work_is_available() { |
| 523 return &work_is_available_; | 538 return &work_is_available_; |
| 524 } | 539 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 { | 667 { |
| 653 AutoLock auto_lock(lock_); | 668 AutoLock auto_lock(lock_); |
| 654 // Send notification that we completed our "work." | 669 // Send notification that we completed our "work." |
| 655 WorkIsCompleted(thread_id); | 670 WorkIsCompleted(thread_id); |
| 656 } | 671 } |
| 657 } | 672 } |
| 658 } | 673 } |
| 659 | 674 |
| 660 } // namespace | 675 } // namespace |
| 661 | 676 |
| OLD | NEW |