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

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

Issue 1177153005: Enables clean VM shutdown. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix error propagation Created 5 years, 4 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 explicit SleepTask(
92 : millis_(millis) { 80 Monitor* sync, int* started_count, int* slept_count, int millis)
81 : sync_(sync),
82 started_count_(started_count),
83 slept_count_(slept_count),
84 millis_(millis) {
93 } 85 }
94 86
95 virtual void Run() { 87 virtual void Run() {
88 {
89 MonitorLocker ml(sync_);
90 *started_count_ = *started_count_ + 1;
91 ml.Notify();
92 }
93 // Sleep so we can be sure the ThreadPool destructor blocks until we're
94 // done.
96 OS::Sleep(millis_); 95 OS::Sleep(millis_);
96 {
97 MonitorLocker ml(sync_);
98 *slept_count_ = *slept_count_ + 1;
99 // No notification here. The main thread is blocked in ThreadPool
100 // shutdown waiting for this thread to finish.
101 }
97 } 102 }
98 103
99 private: 104 private:
105 Monitor* sync_;
106 int* started_count_;
107 int* slept_count_;
100 int millis_; 108 int millis_;
101 }; 109 };
102 110
103 111
104 UNIT_TEST_CASE(ThreadPool_WorkerShutdown) { 112 UNIT_TEST_CASE(ThreadPool_WorkerShutdown) {
105 Monitor exit_sync; 113 const int kTaskCount = 10;
106 int exit_count = 0; 114 Monitor sync;
107 MonitorLocker ml(&exit_sync); 115 int slept_count = 0;
116 int started_count = 0;
108 117
109 // Set up the ThreadPool so that workers notify before they exit. 118 // Set up the ThreadPool so that workers notify before they exit.
110 ThreadPool* thread_pool = new ThreadPool(); 119 ThreadPool* thread_pool = new ThreadPool();
111 ThreadPoolTestPeer::SetExitMonitor(&exit_sync, &exit_count);
112 120
113 // Run a single task. 121 // Run a single task.
114 thread_pool->Run(new SleepTask(2)); 122 for (int i = 0; i < kTaskCount; i++) {
123 thread_pool->Run(new SleepTask(&sync, &started_count, &slept_count, 2));
124 }
115 125
116 // Kill the thread pool. 126 {
127 // Wait for everybody to start.
128 MonitorLocker ml(&sync);
129 while (started_count < kTaskCount) {
130 ml.Wait();
131 }
132 }
133
134 // Kill the thread pool while the workers are sleeping.
117 delete thread_pool; 135 delete thread_pool;
118 thread_pool = NULL; 136 thread_pool = NULL;
119 137
120 // Wait for the workers to terminate. 138 int final_count = 0;
121 while (exit_count == 0) { 139 {
122 ml.Wait(); 140 MonitorLocker ml(&sync);
141 final_count = slept_count;
123 } 142 }
124 EXPECT_EQ(1, exit_count); 143
144 // We should have waited for all the workers to finish, so they all should
145 // have had a chance to increment slept_count.
146 EXPECT_EQ(kTaskCount, final_count);
125 } 147 }
126 148
127 149
128 UNIT_TEST_CASE(ThreadPool_WorkerTimeout) { 150 UNIT_TEST_CASE(ThreadPool_WorkerTimeout) {
129 // Adjust the worker timeout so that we timeout quickly. 151 // Adjust the worker timeout so that we timeout quickly.
130 int saved_timeout = FLAG_worker_timeout_millis; 152 int saved_timeout = FLAG_worker_timeout_millis;
131 FLAG_worker_timeout_millis = 1; 153 FLAG_worker_timeout_millis = 1;
132 154
133 ThreadPool thread_pool; 155 ThreadPool thread_pool;
134 EXPECT_EQ(0U, thread_pool.workers_started()); 156 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) 187 SpawnTask(ThreadPool* pool, Monitor* sync, int todo, int total, int* done)
166 : pool_(pool), sync_(sync), todo_(todo), total_(total), done_(done) { 188 : pool_(pool), sync_(sync), todo_(todo), total_(total), done_(done) {
167 } 189 }
168 190
169 virtual void Run() { 191 virtual void Run() {
170 todo_--; // Subtract one for current task. 192 todo_--; // Subtract one for current task.
171 int child_todo = todo_ / 2; 193 int child_todo = todo_ / 2;
172 194
173 // Spawn 0-2 children. 195 // Spawn 0-2 children.
174 if (todo_ > 0) { 196 if (todo_ > 0) {
175 pool_->Run( 197 pool_->Run(new SpawnTask(
176 new SpawnTask(pool_, sync_, todo_ - child_todo, total_, done_)); 198 pool_, sync_, todo_ - child_todo, total_, done_));
177 } 199 }
178 if (todo_ > 1) { 200 if (todo_ > 1) {
179 pool_->Run( 201 pool_->Run(new SpawnTask(pool_, sync_, child_todo, total_, done_));
180 new SpawnTask(pool_, sync_, child_todo, total_, done_));
181 } 202 }
182 203
183 { 204 {
184 MonitorLocker ml(sync_); 205 MonitorLocker ml(sync_);
185 (*done_)++; 206 (*done_)++;
186 if (*done_ >= total_) { 207 if (*done_ >= total_) {
187 ml.Notify(); 208 ml.Notify();
188 } 209 }
189 } 210 }
190 } 211 }
(...skipping 16 matching lines...) Expand all
207 new SpawnTask(&thread_pool, &sync, kTotalTasks, kTotalTasks, &done)); 228 new SpawnTask(&thread_pool, &sync, kTotalTasks, kTotalTasks, &done));
208 { 229 {
209 MonitorLocker ml(&sync); 230 MonitorLocker ml(&sync);
210 while (done < kTotalTasks) { 231 while (done < kTotalTasks) {
211 ml.Wait(); 232 ml.Wait();
212 } 233 }
213 } 234 }
214 EXPECT_EQ(kTotalTasks, done); 235 EXPECT_EQ(kTotalTasks, done);
215 } 236 }
216 237
217
218 } // namespace dart 238 } // 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