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

Side by Side Diff: base/synchronization/condition_variable_unittest.cc

Issue 2388083002: Test MultiThreadConsumerTest.
Patch Set: Created 4 years, 2 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 | « no previous file | base/synchronization/condition_variable_win.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 Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Multi-threaded tests of ConditionVariable class. 5 // Multi-threaded tests of ConditionVariable class.
6 6
7 #include "base/synchronization/condition_variable.h" 7 #include "base/synchronization/condition_variable.h"
8 8
9 #include <time.h> 9 #include <time.h>
10 10
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 247
248 248
249 // Suddenly got flaky on Win, see http://crbug.com/10607 (starting at 249 // Suddenly got flaky on Win, see http://crbug.com/10607 (starting at
250 // comment #15). 250 // comment #15).
251 #if defined(OS_WIN) 251 #if defined(OS_WIN)
252 #define MAYBE_MultiThreadConsumerTest DISABLED_MultiThreadConsumerTest 252 #define MAYBE_MultiThreadConsumerTest DISABLED_MultiThreadConsumerTest
253 #else 253 #else
254 #define MAYBE_MultiThreadConsumerTest MultiThreadConsumerTest 254 #define MAYBE_MultiThreadConsumerTest MultiThreadConsumerTest
255 #endif 255 #endif
256 // Test serial task servicing, as well as two parallel task servicing methods. 256 // Test serial task servicing, as well as two parallel task servicing methods.
257 TEST_F(ConditionVariableTest, MAYBE_MultiThreadConsumerTest) { 257 TEST_F(ConditionVariableTest, MultiThreadConsumerTest) {
258 const int kThreadCount = 10; 258 int current_test = 0;
259 WorkQueue queue(kThreadCount); // Start the threads. 259 while (++current_test <= 100) {
260 const int kThreadCount = 10;
261 WorkQueue queue(kThreadCount); // Start the threads.
260 262
261 const int kTaskCount = 10; // Number of tasks in each mini-test here. 263 const int kTaskCount = 10; // Number of tasks in each mini-test here.
262 264
263 Time start_time; // Used to time task processing. 265 Time start_time; // Used to time task processing.
264 266
265 { 267 {
266 base::AutoLock auto_lock(*queue.lock()); 268 base::AutoLock auto_lock(*queue.lock());
267 while (!queue.EveryIdWasAllocated()) 269 while (!queue.EveryIdWasAllocated())
268 queue.all_threads_have_ids()->Wait(); 270 queue.all_threads_have_ids()->Wait();
271 }
272
273 // If threads aren't in a wait state, they may start to gobble up tasks in
274 // parallel, short-circuiting (breaking) this test.
275 queue.SpinUntilAllThreadsAreWaiting();
276
277 {
278 // Since we have no tasks yet, all threads should be waiting by now.
279 base::AutoLock auto_lock(*queue.lock());
280 EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
281 EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
282 EXPECT_EQ(0, queue.task_count());
283 EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
284 EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
285 EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
286
287 // Set up to make each task include getting help from another worker, so
288 // so that the work gets done in paralell.
289 queue.ResetHistory();
290 queue.SetTaskCount(kTaskCount);
291 queue.SetWorkTime(kThirtyMs);
292 queue.SetAllowHelp(true);
293
294 start_time = Time::Now();
295 }
296
297 queue.work_is_available()->Signal(); // But each worker can signal another.
298 // Wait till we at least start to handle tasks (and we're not all waiting).
299 queue.SpinUntilTaskCountLessThan(kTaskCount);
300 // Wait to allow the all workers to get done.
301 queue.SpinUntilAllThreadsAreWaiting();
302
303 {
304 // Wait until all work tasks have at least been assigned.
305 base::AutoLock auto_lock(*queue.lock());
306 while (queue.task_count())
307 queue.no_more_tasks()->Wait();
308
309 // To avoid racy assumptions, we'll just assert that at least 2 threads
310 // did work. We know that the first worker should have gone to sleep, and
311 // hence a second worker should have gotten an assignment.
312 EXPECT_LE(2, queue.GetNumThreadsTakingAssignments());
313 EXPECT_EQ(kTaskCount, queue.GetNumberOfCompletedTasks());
314
315 // Try to ask all workers to help, and only a few will do the work.
316 queue.ResetHistory();
317 queue.SetTaskCount(3);
318 queue.SetWorkTime(kThirtyMs);
319 queue.SetAllowHelp(false);
320 }
321 queue.work_is_available()->Broadcast(); // Make them all try.
322 // Wait till we at least start to handle tasks (and we're not all waiting).
323 queue.SpinUntilTaskCountLessThan(3);
324 // Wait to allow the 3 workers to get done.
325 queue.SpinUntilAllThreadsAreWaiting();
326
327 {
328 base::AutoLock auto_lock(*queue.lock());
329 EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
330 EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
331 EXPECT_EQ(0, queue.task_count());
332 EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
333 EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
334 EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
335
336 // Set up to make each task get help from another worker.
337 queue.ResetHistory();
338 queue.SetTaskCount(3);
339 queue.SetWorkTime(kThirtyMs);
340 queue.SetAllowHelp(true); // Allow (unnecessary) help requests.
341 }
342 queue.work_is_available()->Broadcast(); // Signal all threads.
343 // Wait till we at least start to handle tasks (and we're not all waiting).
344 queue.SpinUntilTaskCountLessThan(3);
345 // Wait to allow the 3 workers to get done.
346 queue.SpinUntilAllThreadsAreWaiting();
347
348 {
349 base::AutoLock auto_lock(*queue.lock());
350 EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
351 EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
352 EXPECT_EQ(0, queue.task_count());
353 EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
354 EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
355 EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
356
357 // Set up to make each task get help from another worker.
358 queue.ResetHistory();
359 queue.SetTaskCount(20); // 2 tasks per thread.
360 queue.SetWorkTime(kThirtyMs);
361 queue.SetAllowHelp(true);
362 }
363 queue.work_is_available()->Signal(); // But each worker can signal another.
364 // Wait till we at least start to handle tasks (and we're not all waiting).
365 queue.SpinUntilTaskCountLessThan(20);
366 // Wait to allow the 10 workers to get done.
367 queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
368
369 {
370 base::AutoLock auto_lock(*queue.lock());
371 EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
372 EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
373 EXPECT_EQ(0, queue.task_count());
374 EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
375
376 // Same as last test, but with Broadcast().
377 queue.ResetHistory();
378 queue.SetTaskCount(20); // 2 tasks per thread.
379 queue.SetWorkTime(kThirtyMs);
380 queue.SetAllowHelp(true);
381 }
382 queue.work_is_available()->Broadcast();
383 // Wait till we at least start to handle tasks (and we're not all waiting).
384 queue.SpinUntilTaskCountLessThan(20);
385 // Wait to allow the 10 workers to get done.
386 queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
387
388 {
389 base::AutoLock auto_lock(*queue.lock());
390 EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
391 EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
392 EXPECT_EQ(0, queue.task_count());
393 EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
394
395 queue.SetShutdown();
396 }
397 queue.work_is_available()->Broadcast(); // Force check for shutdown.
398
399 SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(
400 TimeDelta::FromMinutes(1), queue.ThreadSafeCheckShutdown(kThreadCount));
269 } 401 }
270
271 // If threads aren't in a wait state, they may start to gobble up tasks in
272 // parallel, short-circuiting (breaking) this test.
273 queue.SpinUntilAllThreadsAreWaiting();
274
275 {
276 // Since we have no tasks yet, all threads should be waiting by now.
277 base::AutoLock auto_lock(*queue.lock());
278 EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
279 EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
280 EXPECT_EQ(0, queue.task_count());
281 EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
282 EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
283 EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
284
285 // Set up to make each task include getting help from another worker, so
286 // so that the work gets done in paralell.
287 queue.ResetHistory();
288 queue.SetTaskCount(kTaskCount);
289 queue.SetWorkTime(kThirtyMs);
290 queue.SetAllowHelp(true);
291
292 start_time = Time::Now();
293 }
294
295 queue.work_is_available()->Signal(); // But each worker can signal another.
296 // Wait till we at least start to handle tasks (and we're not all waiting).
297 queue.SpinUntilTaskCountLessThan(kTaskCount);
298 // Wait to allow the all workers to get done.
299 queue.SpinUntilAllThreadsAreWaiting();
300
301 {
302 // Wait until all work tasks have at least been assigned.
303 base::AutoLock auto_lock(*queue.lock());
304 while (queue.task_count())
305 queue.no_more_tasks()->Wait();
306
307 // To avoid racy assumptions, we'll just assert that at least 2 threads
308 // did work. We know that the first worker should have gone to sleep, and
309 // hence a second worker should have gotten an assignment.
310 EXPECT_LE(2, queue.GetNumThreadsTakingAssignments());
311 EXPECT_EQ(kTaskCount, queue.GetNumberOfCompletedTasks());
312
313 // Try to ask all workers to help, and only a few will do the work.
314 queue.ResetHistory();
315 queue.SetTaskCount(3);
316 queue.SetWorkTime(kThirtyMs);
317 queue.SetAllowHelp(false);
318 }
319 queue.work_is_available()->Broadcast(); // Make them all try.
320 // Wait till we at least start to handle tasks (and we're not all waiting).
321 queue.SpinUntilTaskCountLessThan(3);
322 // Wait to allow the 3 workers to get done.
323 queue.SpinUntilAllThreadsAreWaiting();
324
325 {
326 base::AutoLock auto_lock(*queue.lock());
327 EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
328 EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
329 EXPECT_EQ(0, queue.task_count());
330 EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
331 EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
332 EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
333
334 // Set up to make each task get help from another worker.
335 queue.ResetHistory();
336 queue.SetTaskCount(3);
337 queue.SetWorkTime(kThirtyMs);
338 queue.SetAllowHelp(true); // Allow (unnecessary) help requests.
339 }
340 queue.work_is_available()->Broadcast(); // Signal all threads.
341 // Wait till we at least start to handle tasks (and we're not all waiting).
342 queue.SpinUntilTaskCountLessThan(3);
343 // Wait to allow the 3 workers to get done.
344 queue.SpinUntilAllThreadsAreWaiting();
345
346 {
347 base::AutoLock auto_lock(*queue.lock());
348 EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
349 EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
350 EXPECT_EQ(0, queue.task_count());
351 EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
352 EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
353 EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
354
355 // Set up to make each task get help from another worker.
356 queue.ResetHistory();
357 queue.SetTaskCount(20); // 2 tasks per thread.
358 queue.SetWorkTime(kThirtyMs);
359 queue.SetAllowHelp(true);
360 }
361 queue.work_is_available()->Signal(); // But each worker can signal another.
362 // Wait till we at least start to handle tasks (and we're not all waiting).
363 queue.SpinUntilTaskCountLessThan(20);
364 // Wait to allow the 10 workers to get done.
365 queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
366
367 {
368 base::AutoLock auto_lock(*queue.lock());
369 EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
370 EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
371 EXPECT_EQ(0, queue.task_count());
372 EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
373
374 // Same as last test, but with Broadcast().
375 queue.ResetHistory();
376 queue.SetTaskCount(20); // 2 tasks per thread.
377 queue.SetWorkTime(kThirtyMs);
378 queue.SetAllowHelp(true);
379 }
380 queue.work_is_available()->Broadcast();
381 // Wait till we at least start to handle tasks (and we're not all waiting).
382 queue.SpinUntilTaskCountLessThan(20);
383 // Wait to allow the 10 workers to get done.
384 queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
385
386 {
387 base::AutoLock auto_lock(*queue.lock());
388 EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
389 EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
390 EXPECT_EQ(0, queue.task_count());
391 EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
392
393 queue.SetShutdown();
394 }
395 queue.work_is_available()->Broadcast(); // Force check for shutdown.
396
397 SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
398 queue.ThreadSafeCheckShutdown(kThreadCount));
399 } 402 }
400 403
401 TEST_F(ConditionVariableTest, LargeFastTaskTest) { 404 TEST_F(ConditionVariableTest, LargeFastTaskTest) {
402 const int kThreadCount = 200; 405 const int kThreadCount = 200;
403 WorkQueue queue(kThreadCount); // Start the threads. 406 WorkQueue queue(kThreadCount); // Start the threads.
404 407
405 Lock private_lock; // Used locally for master to wait. 408 Lock private_lock; // Used locally for master to wait.
406 base::AutoLock private_held_lock(private_lock); 409 base::AutoLock private_held_lock(private_lock);
407 ConditionVariable private_cv(&private_lock); 410 ConditionVariable private_cv(&private_lock);
408 411
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 base::AutoLock auto_lock(lock_); 762 base::AutoLock auto_lock(lock_);
760 // Send notification that we completed our "work." 763 // Send notification that we completed our "work."
761 WorkIsCompleted(thread_id); 764 WorkIsCompleted(thread_id);
762 } 765 }
763 } 766 }
764 } 767 }
765 768
766 } // namespace 769 } // namespace
767 770
768 } // namespace base 771 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | base/synchronization/condition_variable_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698