Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: runtime/vm/thread_pool_test.cc

Issue 1275353005: VM thread shutdown. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Merge Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/thread_pool.cc ('k') | runtime/vm/verified_memory_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/os.h" 5 #include "vm/os.h"
6 #include "vm/lockers.h" 6 #include "vm/lockers.h"
7 #include "vm/thread_pool.h" 7 #include "vm/thread_pool.h"
8 #include "vm/unit_test.h" 8 #include "vm/unit_test.h"
9 9
10 namespace dart { 10 namespace dart {
11 11
12 DECLARE_FLAG(int, worker_timeout_millis); 12 DECLARE_FLAG(int, worker_timeout_millis);
13 13
14 14
15 class ThreadPoolTestPeer {
16 public:
17 // When the pool has an exit monitor, workers notify a monitor just
18 // before they exit. This is only used in tests to make sure that
19 // Shutdown works.
20 static void SetExitMonitor(Monitor* exit_monitor, int* exit_count) {
21 ThreadPool::exit_monitor_ = exit_monitor;
22 ThreadPool::exit_count_ = exit_count;
23 }
24 };
25
26
27 UNIT_TEST_CASE(ThreadPool_Create) { 15 UNIT_TEST_CASE(ThreadPool_Create) {
28 ThreadPool thread_pool; 16 ThreadPool thread_pool;
29 } 17 }
30 18
31 19
32 class TestTask : public ThreadPool::Task { 20 class TestTask : public ThreadPool::Task {
33 public: 21 public:
34 TestTask(Monitor* sync, bool* done) 22 TestTask(Monitor* sync, bool* done)
35 : sync_(sync), done_(done) { 23 : sync_(sync), done_(done) {
36 } 24 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 while (!done[i]) { 69 while (!done[i]) {
82 ml.Wait(); 70 ml.Wait();
83 } 71 }
84 EXPECT(done[i]); 72 EXPECT(done[i]);
85 } 73 }
86 } 74 }
87 75
88 76
89 class SleepTask : public ThreadPool::Task { 77 class SleepTask : public ThreadPool::Task {
90 public: 78 public:
91 explicit SleepTask(int millis) 79 SleepTask(Monitor* sync, int* started_count, int* slept_count, int millis)
92 : millis_(millis) { 80 : sync_(sync),
81 started_count_(started_count),
82 slept_count_(slept_count),
83 millis_(millis) {
93 } 84 }
94 85
95 virtual void Run() { 86 virtual void Run() {
87 {
88 MonitorLocker ml(sync_);
89 *started_count_ = *started_count_ + 1;
90 ml.Notify();
91 }
92 // Sleep so we can be sure the ThreadPool destructor blocks until we're
93 // done.
96 OS::Sleep(millis_); 94 OS::Sleep(millis_);
95 {
96 MonitorLocker ml(sync_);
97 *slept_count_ = *slept_count_ + 1;
98 // No notification here. The main thread is blocked in ThreadPool
99 // shutdown waiting for this thread to finish.
100 }
97 } 101 }
98 102
99 private: 103 private:
104 Monitor* sync_;
105 int* started_count_;
106 int* slept_count_;
100 int millis_; 107 int millis_;
101 }; 108 };
102 109
103 110
104 UNIT_TEST_CASE(ThreadPool_WorkerShutdown) { 111 UNIT_TEST_CASE(ThreadPool_WorkerShutdown) {
105 Monitor exit_sync; 112 const int kTaskCount = 10;
106 int exit_count = 0; 113 Monitor sync;
107 MonitorLocker ml(&exit_sync); 114 int slept_count = 0;
115 int started_count = 0;
108 116
109 // Set up the ThreadPool so that workers notify before they exit. 117 // Set up the ThreadPool so that workers notify before they exit.
110 ThreadPool* thread_pool = new ThreadPool(); 118 ThreadPool* thread_pool = new ThreadPool();
111 ThreadPoolTestPeer::SetExitMonitor(&exit_sync, &exit_count);
112 119
113 // Run a single task. 120 // Run a single task.
114 thread_pool->Run(new SleepTask(2)); 121 for (int i = 0; i < kTaskCount; i++) {
122 thread_pool->Run(new SleepTask(&sync, &started_count, &slept_count, 2));
123 }
115 124
116 // Kill the thread pool. 125 {
126 // Wait for everybody to start.
127 MonitorLocker ml(&sync);
128 while (started_count < kTaskCount) {
129 ml.Wait();
130 }
131 }
132
133 // Kill the thread pool while the workers are sleeping.
117 delete thread_pool; 134 delete thread_pool;
118 thread_pool = NULL; 135 thread_pool = NULL;
119 136
120 // Wait for the workers to terminate. 137 int final_count = 0;
121 while (exit_count == 0) { 138 {
122 ml.Wait(); 139 MonitorLocker ml(&sync);
140 final_count = slept_count;
123 } 141 }
124 EXPECT_EQ(1, exit_count); 142
143 // We should have waited for all the workers to finish, so they all should
144 // have had a chance to increment slept_count.
145 EXPECT_EQ(kTaskCount, final_count);
125 } 146 }
126 147
127 148
128 UNIT_TEST_CASE(ThreadPool_WorkerTimeout) { 149 UNIT_TEST_CASE(ThreadPool_WorkerTimeout) {
129 // Adjust the worker timeout so that we timeout quickly. 150 // Adjust the worker timeout so that we timeout quickly.
130 int saved_timeout = FLAG_worker_timeout_millis; 151 int saved_timeout = FLAG_worker_timeout_millis;
131 FLAG_worker_timeout_millis = 1; 152 FLAG_worker_timeout_millis = 1;
132 153
133 ThreadPool thread_pool; 154 ThreadPool thread_pool;
134 EXPECT_EQ(0U, thread_pool.workers_started()); 155 EXPECT_EQ(0U, thread_pool.workers_started());
(...skipping 30 matching lines...) Expand all
165 SpawnTask(ThreadPool* pool, Monitor* sync, int todo, int total, int* done) 186 SpawnTask(ThreadPool* pool, Monitor* sync, int todo, int total, int* done)
166 : pool_(pool), sync_(sync), todo_(todo), total_(total), done_(done) { 187 : pool_(pool), sync_(sync), todo_(todo), total_(total), done_(done) {
167 } 188 }
168 189
169 virtual void Run() { 190 virtual void Run() {
170 todo_--; // Subtract one for current task. 191 todo_--; // Subtract one for current task.
171 int child_todo = todo_ / 2; 192 int child_todo = todo_ / 2;
172 193
173 // Spawn 0-2 children. 194 // Spawn 0-2 children.
174 if (todo_ > 0) { 195 if (todo_ > 0) {
175 pool_->Run( 196 pool_->Run(new SpawnTask(
176 new SpawnTask(pool_, sync_, todo_ - child_todo, total_, done_)); 197 pool_, sync_, todo_ - child_todo, total_, done_));
177 } 198 }
178 if (todo_ > 1) { 199 if (todo_ > 1) {
179 pool_->Run( 200 pool_->Run(new SpawnTask(pool_, sync_, child_todo, total_, done_));
180 new SpawnTask(pool_, sync_, child_todo, total_, done_));
181 } 201 }
182 202
183 { 203 {
184 MonitorLocker ml(sync_); 204 MonitorLocker ml(sync_);
185 (*done_)++; 205 (*done_)++;
186 if (*done_ >= total_) { 206 if (*done_ >= total_) {
187 ml.Notify(); 207 ml.Notify();
188 } 208 }
189 } 209 }
190 } 210 }
(...skipping 16 matching lines...) Expand all
207 new SpawnTask(&thread_pool, &sync, kTotalTasks, kTotalTasks, &done)); 227 new SpawnTask(&thread_pool, &sync, kTotalTasks, kTotalTasks, &done));
208 { 228 {
209 MonitorLocker ml(&sync); 229 MonitorLocker ml(&sync);
210 while (done < kTotalTasks) { 230 while (done < kTotalTasks) {
211 ml.Wait(); 231 ml.Wait();
212 } 232 }
213 } 233 }
214 EXPECT_EQ(kTotalTasks, done); 234 EXPECT_EQ(kTotalTasks, done);
215 } 235 }
216 236
217
218 } // namespace dart 237 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/thread_pool.cc ('k') | runtime/vm/verified_memory_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698