Index: runtime/vm/thread_pool_test.cc |
diff --git a/runtime/vm/thread_pool_test.cc b/runtime/vm/thread_pool_test.cc |
index af9f618e7edb541e6849d0ae39199bc0888a5db0..35a61273736c8e80c45f957263f596c289421dcd 100644 |
--- a/runtime/vm/thread_pool_test.cc |
+++ b/runtime/vm/thread_pool_test.cc |
@@ -12,6 +12,18 @@ 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; |
} |
@@ -76,74 +88,40 @@ UNIT_TEST_CASE(ThreadPool_RunMany) { |
class SleepTask : public ThreadPool::Task { |
public: |
- explicit SleepTask( |
- Monitor* sync, int* started_count, int* slept_count, int millis) |
- : sync_(sync), |
- started_count_(started_count), |
- slept_count_(slept_count), |
- millis_(millis) { |
+ explicit SleepTask(int millis) |
+ : 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) { |
- const int kTaskCount = 10; |
- Monitor sync; |
- int slept_count = 0; |
- int started_count = 0; |
+ Monitor exit_sync; |
+ int exit_count = 0; |
+ MonitorLocker ml(&exit_sync); |
// 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. |
- 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(); |
- } |
- } |
+ thread_pool->Run(new SleepTask(2)); |
- // Kill the thread pool while the workers are sleeping. |
+ // Kill the thread pool. |
delete thread_pool; |
thread_pool = NULL; |
- int final_count = 0; |
- { |
- MonitorLocker ml(&sync); |
- final_count = slept_count; |
+ // Wait for the workers to terminate. |
+ while (exit_count == 0) { |
+ ml.Wait(); |
} |
- |
- // 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); |
+ EXPECT_EQ(1, exit_count); |
} |
@@ -194,11 +172,12 @@ 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_)); |
} |
{ |
@@ -235,4 +214,5 @@ UNIT_TEST_CASE(ThreadPool_RecursiveSpawn) { |
EXPECT_EQ(kTotalTasks, done); |
} |
+ |
} // namespace dart |