Chromium Code Reviews| Index: runtime/vm/thread_pool_test.cc |
| diff --git a/runtime/vm/thread_pool_test.cc b/runtime/vm/thread_pool_test.cc |
| index 35a61273736c8e80c45f957263f596c289421dcd..af9f618e7edb541e6849d0ae39199bc0888a5db0 100644 |
| --- a/runtime/vm/thread_pool_test.cc |
| +++ b/runtime/vm/thread_pool_test.cc |
| @@ -12,18 +12,6 @@ namespace dart { |
| DECLARE_FLAG(int, worker_timeout_millis); |
| -class ThreadPoolTestPeer { |
| - public: |
| - // When the pool has an exit monitor, workers notify a monitor just |
| - // before they exit. This is only used in tests to make sure that |
| - // Shutdown works. |
| - static void SetExitMonitor(Monitor* exit_monitor, int* exit_count) { |
| - ThreadPool::exit_monitor_ = exit_monitor; |
| - ThreadPool::exit_count_ = exit_count; |
| - } |
| -}; |
| - |
| - |
| UNIT_TEST_CASE(ThreadPool_Create) { |
| ThreadPool thread_pool; |
| } |
| @@ -88,40 +76,74 @@ UNIT_TEST_CASE(ThreadPool_RunMany) { |
| class SleepTask : public ThreadPool::Task { |
| public: |
| - explicit SleepTask(int millis) |
| - : millis_(millis) { |
| + explicit SleepTask( |
|
Ivan Posva
2015/09/14 21:52:14
Drop the explicit!
zra
2015/09/14 22:59:01
Done.
|
| + Monitor* sync, int* started_count, int* slept_count, int millis) |
| + : sync_(sync), |
| + started_count_(started_count), |
| + slept_count_(slept_count), |
| + millis_(millis) { |
| } |
| virtual void Run() { |
| + { |
| + MonitorLocker ml(sync_); |
| + *started_count_ = *started_count_ + 1; |
| + ml.Notify(); |
| + } |
| + // Sleep so we can be sure the ThreadPool destructor blocks until we're |
| + // done. |
| OS::Sleep(millis_); |
| + { |
| + MonitorLocker ml(sync_); |
| + *slept_count_ = *slept_count_ + 1; |
| + // No notification here. The main thread is blocked in ThreadPool |
| + // shutdown waiting for this thread to finish. |
| + } |
| } |
| private: |
| + Monitor* sync_; |
| + int* started_count_; |
| + int* slept_count_; |
| int millis_; |
| }; |
| UNIT_TEST_CASE(ThreadPool_WorkerShutdown) { |
| - Monitor exit_sync; |
| - int exit_count = 0; |
| - MonitorLocker ml(&exit_sync); |
| + const int kTaskCount = 10; |
| + Monitor sync; |
| + int slept_count = 0; |
| + int started_count = 0; |
| // Set up the ThreadPool so that workers notify before they exit. |
| ThreadPool* thread_pool = new ThreadPool(); |
| - ThreadPoolTestPeer::SetExitMonitor(&exit_sync, &exit_count); |
| // Run a single task. |
| - thread_pool->Run(new SleepTask(2)); |
| + for (int i = 0; i < kTaskCount; i++) { |
| + thread_pool->Run(new SleepTask(&sync, &started_count, &slept_count, 2)); |
| + } |
| + |
| + { |
| + // Wait for everybody to start. |
| + MonitorLocker ml(&sync); |
| + while (started_count < kTaskCount) { |
| + ml.Wait(); |
| + } |
| + } |
| - // Kill the thread pool. |
| + // Kill the thread pool while the workers are sleeping. |
| delete thread_pool; |
| thread_pool = NULL; |
| - // Wait for the workers to terminate. |
| - while (exit_count == 0) { |
| - ml.Wait(); |
| + int final_count = 0; |
| + { |
| + MonitorLocker ml(&sync); |
| + final_count = slept_count; |
| } |
| - EXPECT_EQ(1, exit_count); |
| + |
| + // We should have waited for all the workers to finish, so they all should |
| + // have had a chance to increment slept_count. |
| + EXPECT_EQ(kTaskCount, final_count); |
| } |
| @@ -172,12 +194,11 @@ class SpawnTask : public ThreadPool::Task { |
| // Spawn 0-2 children. |
| if (todo_ > 0) { |
| - pool_->Run( |
| - new SpawnTask(pool_, sync_, todo_ - child_todo, total_, done_)); |
| + pool_->Run(new SpawnTask( |
| + pool_, sync_, todo_ - child_todo, total_, done_)); |
| } |
| if (todo_ > 1) { |
| - pool_->Run( |
| - new SpawnTask(pool_, sync_, child_todo, total_, done_)); |
| + pool_->Run(new SpawnTask(pool_, sync_, child_todo, total_, done_)); |
| } |
| { |
| @@ -214,5 +235,4 @@ UNIT_TEST_CASE(ThreadPool_RecursiveSpawn) { |
| EXPECT_EQ(kTotalTasks, done); |
| } |
| - |
| } // namespace dart |