v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-condition-variable.cc
Go to the documentation of this file.
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "cctest.h"
32 #include "platform/time.h"
33 
34 using namespace ::v8::internal;
35 
36 
37 TEST(WaitForAfterNofityOnSameThread) {
38  for (int n = 0; n < 10; ++n) {
39  Mutex mutex;
40  ConditionVariable cv;
41 
42  LockGuard<Mutex> lock_guard(&mutex);
43 
44  cv.NotifyOne();
45  CHECK_EQ(false, cv.WaitFor(&mutex, TimeDelta::FromMicroseconds(n)));
46 
47  cv.NotifyAll();
48  CHECK_EQ(false, cv.WaitFor(&mutex, TimeDelta::FromMicroseconds(n)));
49  }
50 }
51 
52 
53 class ThreadWithMutexAndConditionVariable V8_FINAL : public Thread {
54  public:
56  : Thread("ThreadWithMutexAndConditionVariable"),
57  running_(false), finished_(false) {}
59 
60  virtual void Run() V8_OVERRIDE {
61  LockGuard<Mutex> lock_guard(&mutex_);
62  running_ = true;
63  cv_.NotifyOne();
64  while (running_) {
65  cv_.Wait(&mutex_);
66  }
67  finished_ = true;
68  cv_.NotifyAll();
69  }
70 
71  bool running_;
72  bool finished_;
73  ConditionVariable cv_;
74  Mutex mutex_;
75 };
76 
77 
78 TEST(MultipleThreadsWithSeparateConditionVariables) {
79  static const int kThreadCount = 128;
80  ThreadWithMutexAndConditionVariable threads[kThreadCount];
81 
82  for (int n = 0; n < kThreadCount; ++n) {
83  LockGuard<Mutex> lock_guard(&threads[n].mutex_);
84  CHECK(!threads[n].running_);
85  CHECK(!threads[n].finished_);
86  threads[n].Start();
87  // Wait for nth thread to start.
88  while (!threads[n].running_) {
89  threads[n].cv_.Wait(&threads[n].mutex_);
90  }
91  }
92 
93  for (int n = kThreadCount - 1; n >= 0; --n) {
94  LockGuard<Mutex> lock_guard(&threads[n].mutex_);
95  CHECK(threads[n].running_);
96  CHECK(!threads[n].finished_);
97  }
98 
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;
105  threads[n].cv_.NotifyOne();
106  }
107 
108  for (int n = kThreadCount - 1; n >= 0; --n) {
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) {
119  threads[n].Join();
120  LockGuard<Mutex> lock_guard(&threads[n].mutex_);
121  CHECK(!threads[n].running_);
122  CHECK(threads[n].finished_);
123  }
124 }
125 
126 
127 class ThreadWithSharedMutexAndConditionVariable V8_FINAL : public Thread {
128  public:
130  : Thread("ThreadWithSharedMutexAndConditionVariable"),
131  running_(false), finished_(false), cv_(NULL), mutex_(NULL) {}
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 
229 
230 class LoopIncrementThread V8_FINAL : public Thread {
231  public:
233  int* counter,
234  int limit,
235  int thread_count,
236  ConditionVariable* cv,
237  Mutex* mutex)
238  : Thread("LoopIncrementThread"), rem_(rem), counter_(counter),
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  }
243 
244  virtual void Run() V8_OVERRIDE {
245  int last_count = -1;
246  while (true) {
247  LockGuard<Mutex> lock_guard(mutex_);
248  int count = *counter_;
249  while (count % thread_count_ != rem_ && count < limit_) {
250  cv_->Wait(mutex_);
251  count = *counter_;
252  }
253  if (count >= limit_) break;
254  CHECK_EQ(*counter_, count);
255  if (last_count != -1) {
256  CHECK_EQ(last_count + (thread_count_ - 1), count);
257  }
258  count++;
259  *counter_ = count;
260  last_count = count;
261  cv_->NotifyAll();
262  }
263  }
264 
265  private:
266  const int rem_;
267  int* counter_;
268  const int limit_;
269  const int thread_count_;
270  ConditionVariable* cv_;
271  Mutex* mutex_;
272 };
273 
274 
275 TEST(LoopIncrement) {
276  static const int kMaxThreadCount = 16;
277  Mutex mutex;
278  ConditionVariable cv;
279  for (int thread_count = 1; thread_count < kMaxThreadCount; ++thread_count) {
280  int limit = thread_count * 100;
281  int counter = 0;
282 
283  // Setup the threads.
284  Thread** threads = new Thread*[thread_count];
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  }
304 }
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
#define CHECK_EQ(expected, value)
Definition: checks.h:252
TEST(WaitForAfterNofityOnSameThread)
ThreadWithSharedMutexAndConditionVariable()
#define CHECK_LT(a, b)
Definition: checks.h:262
#define CHECK(condition)
Definition: checks.h:75
virtual ~ThreadWithMutexAndConditionVariable()
ConditionVariable * cv_
ConditionVariable cv_
#define V8_OVERRIDE
Definition: v8config.h:402
virtual ~ThreadWithSharedMutexAndConditionVariable()
LoopIncrementThread(int rem, int *counter, int limit, int thread_count, ConditionVariable *cv, Mutex *mutex)
virtual void Run() V8_OVERRIDE