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