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

Side by Side Diff: test/cctest/test-condition-variable.cc

Issue 23604027: Improve cctest/test-condition-variable. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 public: 54 public:
55 ThreadWithMutexAndConditionVariable() 55 ThreadWithMutexAndConditionVariable()
56 : Thread("ThreadWithMutexAndConditionVariable"), 56 : Thread("ThreadWithMutexAndConditionVariable"),
57 running_(false), finished_(false) {} 57 running_(false), finished_(false) {}
58 virtual ~ThreadWithMutexAndConditionVariable() {} 58 virtual ~ThreadWithMutexAndConditionVariable() {}
59 59
60 virtual void Run() V8_OVERRIDE { 60 virtual void Run() V8_OVERRIDE {
61 LockGuard<Mutex> lock_guard(&mutex_); 61 LockGuard<Mutex> lock_guard(&mutex_);
62 running_ = true; 62 running_ = true;
63 cv_.NotifyOne(); 63 cv_.NotifyOne();
64 cv_.Wait(&mutex_); 64 while (running_) {
65 running_ = false; 65 cv_.Wait(&mutex_);
66 }
66 finished_ = true; 67 finished_ = true;
67 cv_.NotifyOne(); 68 cv_.NotifyAll();
68 } 69 }
69 70
70 volatile bool running_; 71 bool running_;
71 volatile bool finished_; 72 bool finished_;
72 ConditionVariable cv_; 73 ConditionVariable cv_;
73 Mutex mutex_; 74 Mutex mutex_;
74 }; 75 };
75 76
76 77
77 TEST(MultipleThreadsWithSeparateConditionVariables) { 78 TEST(MultipleThreadsWithSeparateConditionVariables) {
78 static const int kThreadCount = 16; 79 static const int kThreadCount = 128;
79 static const TimeDelta kMaxThreadStartTime =
80 TimeDelta::FromMilliseconds(250) * kThreadCount;
81 ThreadWithMutexAndConditionVariable threads[kThreadCount]; 80 ThreadWithMutexAndConditionVariable threads[kThreadCount];
82 81
83 for (int n = 0; n < kThreadCount; ++n) { 82 for (int n = 0; n < kThreadCount; ++n) {
84 LockGuard<Mutex> lock_guard(&threads[n].mutex_); 83 LockGuard<Mutex> lock_guard(&threads[n].mutex_);
85 CHECK(!threads[n].running_); 84 CHECK(!threads[n].running_);
86 CHECK(!threads[n].finished_); 85 CHECK(!threads[n].finished_);
87 threads[n].Start(); 86 threads[n].Start();
88 // Wait for nth thread to start. 87 // Wait for nth thread to start.
89 CHECK(threads[n].cv_.WaitFor(&threads[n].mutex_, kMaxThreadStartTime)); 88 while (!threads[n].running_) {
89 threads[n].cv_.Wait(&threads[n].mutex_);
90 }
90 } 91 }
91 92
92 for (int n = kThreadCount - 1; n >= 0; --n) { 93 for (int n = kThreadCount - 1; n >= 0; --n) {
93 LockGuard<Mutex> lock_guard(&threads[n].mutex_); 94 LockGuard<Mutex> lock_guard(&threads[n].mutex_);
94 CHECK(threads[n].running_); 95 CHECK(threads[n].running_);
95 CHECK(!threads[n].finished_); 96 CHECK(!threads[n].finished_);
96 } 97 }
97 98
98 for (int n = 0; n < kThreadCount; ++n) { 99 for (int n = 0; n < kThreadCount; ++n) {
100 LockGuard<Mutex> lock_guard(&threads[n].mutex_);
101 CHECK(threads[n].running_);
102 CHECK(!threads[n].finished_);
103 // Tell the nth thread to quit.
104 threads[n].running_ = false;
99 threads[n].cv_.NotifyOne(); 105 threads[n].cv_.NotifyOne();
100 } 106 }
101 107
102 for (int n = kThreadCount - 1; n >= 0; --n) { 108 for (int n = kThreadCount - 1; n >= 0; --n) {
103 // Wait for nth thread to quit. 109 // Wait for nth thread to quit.
110 LockGuard<Mutex> lock_guard(&threads[n].mutex_);
111 while (!threads[n].finished_) {
112 threads[n].cv_.Wait(&threads[n].mutex_);
113 }
114 CHECK(!threads[n].running_);
115 CHECK(threads[n].finished_);
116 }
117
118 for (int n = 0; n < kThreadCount; ++n) {
104 threads[n].Join(); 119 threads[n].Join();
105 LockGuard<Mutex> lock_guard(&threads[n].mutex_); 120 LockGuard<Mutex> lock_guard(&threads[n].mutex_);
106 CHECK(!threads[n].running_); 121 CHECK(!threads[n].running_);
107 CHECK(threads[n].finished_); 122 CHECK(threads[n].finished_);
108 } 123 }
109 } 124 }
110 125
111 126
112 static int loop_counter = 0; 127 class ThreadWithSharedMutexAndConditionVariable V8_FINAL : public Thread {
113 static const int kLoopCounterLimit = 100; 128 public:
129 ThreadWithSharedMutexAndConditionVariable()
130 : Thread("ThreadWithSharedMutexAndConditionVariable"),
131 running_(false), finished_(false), cv_(NULL), mutex_(NULL) {}
132 virtual ~ThreadWithSharedMutexAndConditionVariable() {}
133
134 virtual void Run() V8_OVERRIDE {
135 LockGuard<Mutex> lock_guard(mutex_);
136 running_ = true;
137 cv_->NotifyAll();
138 while (running_) {
139 cv_->Wait(mutex_);
140 }
141 finished_ = true;
142 cv_->NotifyAll();
143 }
144
145 bool running_;
146 bool finished_;
147 ConditionVariable* cv_;
148 Mutex* mutex_;
149 };
150
151
152 TEST(MultipleThreadsWithSharedSeparateConditionVariables) {
153 static const int kThreadCount = 128;
154 ThreadWithSharedMutexAndConditionVariable threads[kThreadCount];
155 ConditionVariable cv;
156 Mutex mutex;
157
158 for (int n = 0; n < kThreadCount; ++n) {
159 threads[n].mutex_ = &mutex;
160 threads[n].cv_ = &cv;
161 }
162
163 // Start all threads.
164 {
165 LockGuard<Mutex> lock_guard(&mutex);
166 for (int n = 0; n < kThreadCount; ++n) {
167 CHECK(!threads[n].running_);
168 CHECK(!threads[n].finished_);
169 threads[n].Start();
170 }
171 }
172
173 // Wait for all threads to start.
174 {
175 LockGuard<Mutex> lock_guard(&mutex);
176 for (int n = kThreadCount - 1; n >= 0; --n) {
177 while (!threads[n].running_) {
178 cv.Wait(&mutex);
179 }
180 }
181 }
182
183 // Make sure that all threads are running.
184 {
185 LockGuard<Mutex> lock_guard(&mutex);
186 for (int n = 0; n < kThreadCount; ++n) {
187 CHECK(threads[n].running_);
188 CHECK(!threads[n].finished_);
189 }
190 }
191
192 // Tell all threads to quit.
193 {
194 LockGuard<Mutex> lock_guard(&mutex);
195 for (int n = kThreadCount - 1; n >= 0; --n) {
196 CHECK(threads[n].running_);
197 CHECK(!threads[n].finished_);
198 // Tell the nth thread to quit.
199 threads[n].running_ = false;
200 }
201 cv.NotifyAll();
202 }
203
204 // Wait for all threads to quit.
205 {
206 LockGuard<Mutex> lock_guard(&mutex);
207 for (int n = 0; n < kThreadCount; ++n) {
208 while (!threads[n].finished_) {
209 cv.Wait(&mutex);
210 }
211 }
212 }
213
214 // Make sure all threads are finished.
215 {
216 LockGuard<Mutex> lock_guard(&mutex);
217 for (int n = kThreadCount - 1; n >= 0; --n) {
218 CHECK(!threads[n].running_);
219 CHECK(threads[n].finished_);
220 }
221 }
222
223 // Join all threads.
224 for (int n = 0; n < kThreadCount; ++n) {
225 threads[n].Join();
226 }
227 }
228
114 229
115 class LoopIncrementThread V8_FINAL : public Thread { 230 class LoopIncrementThread V8_FINAL : public Thread {
116 public: 231 public:
117 LoopIncrementThread(const char* name, 232 LoopIncrementThread(int rem,
118 int rem, 233 int* counter,
234 int limit,
235 int thread_count,
119 ConditionVariable* cv, 236 ConditionVariable* cv,
120 Mutex* mutex) 237 Mutex* mutex)
121 : Thread(name), rem_(rem), cv_(cv), mutex_(mutex) {} 238 : Thread("LoopIncrementThread"), rem_(rem), counter_(counter),
122 virtual ~LoopIncrementThread() {} 239 limit_(limit), thread_count_(thread_count), cv_(cv), mutex_(mutex) {
240 CHECK_LT(rem, thread_count);
241 CHECK_EQ(0, limit % thread_count);
242 }
123 243
124 virtual void Run() V8_OVERRIDE { 244 virtual void Run() V8_OVERRIDE {
125 int last_count = -1; 245 int last_count = -1;
126 while (true) { 246 while (true) {
127 LockGuard<Mutex> lock_guard(mutex_); 247 LockGuard<Mutex> lock_guard(mutex_);
128 int count = loop_counter; 248 int count = *counter_;
129 while (count % 2 != rem_ && count < kLoopCounterLimit) { 249 while (count % thread_count_ != rem_ && count < limit_) {
130 cv_->Wait(mutex_); 250 cv_->Wait(mutex_);
131 count = loop_counter; 251 count = *counter_;
132 } 252 }
133 if (count >= kLoopCounterLimit) break; 253 if (count >= limit_) break;
134 CHECK_EQ(loop_counter, count); 254 CHECK_EQ(*counter_, count);
135 if (last_count != -1) { 255 if (last_count != -1) {
136 CHECK_EQ(last_count + 1, count); 256 CHECK_EQ(last_count + (thread_count_ - 1), count);
137 } 257 }
138 count++; 258 count++;
139 loop_counter = count; 259 *counter_ = count;
140 last_count = count; 260 last_count = count;
141 cv_->NotifyOne(); 261 cv_->NotifyAll();
142 } 262 }
143 } 263 }
144 264
145 private: 265 private:
146 const int rem_; 266 const int rem_;
267 int* counter_;
268 const int limit_;
269 const int thread_count_;
147 ConditionVariable* cv_; 270 ConditionVariable* cv_;
148 Mutex* mutex_; 271 Mutex* mutex_;
149 }; 272 };
150 273
151 274
152 TEST(LoopIncrement) { 275 TEST(LoopIncrement) {
276 static const int kMaxThreadCount = 16;
153 Mutex mutex; 277 Mutex mutex;
154 ConditionVariable cv; 278 ConditionVariable cv;
155 LoopIncrementThread t0("t0", 0, &cv, &mutex); 279 for (int thread_count = 1; thread_count < kMaxThreadCount; ++thread_count) {
156 LoopIncrementThread t1("t1", 1, &cv, &mutex); 280 int limit = thread_count * 100;
157 t0.Start(); 281 int counter = 0;
158 t1.Start(); 282
159 t0.Join(); 283 // Setup the threads.
160 t1.Join(); 284 Thread** threads = new Thread*[thread_count];
161 CHECK_EQ(kLoopCounterLimit, loop_counter); 285 for (int n = 0; n < thread_count; ++n) {
286 threads[n] = new LoopIncrementThread(
287 n, &counter, limit, thread_count, &cv, &mutex);
288 }
289
290 // Start all threads.
291 for (int n = thread_count - 1; n >= 0; --n) {
292 threads[n]->Start();
293 }
294
295 // Join and cleanup all threads.
296 for (int n = 0; n < thread_count; ++n) {
297 threads[n]->Join();
298 delete threads[n];
299 }
300 delete[] threads;
301
302 CHECK_EQ(limit, counter);
303 }
162 } 304 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698