| Index: base/synchronization/condition_variable_unittest.cc
|
| diff --git a/base/synchronization/condition_variable_unittest.cc b/base/synchronization/condition_variable_unittest.cc
|
| index d60b2b8af58aa55c48886933c7682fb452d9f963..5656a73c93675d038c6d54ab926935f57d12e4cc 100644
|
| --- a/base/synchronization/condition_variable_unittest.cc
|
| +++ b/base/synchronization/condition_variable_unittest.cc
|
| @@ -254,148 +254,151 @@ TEST_F(ConditionVariableTest, DISABLED_TimeoutAcrossSetTimeOfDay) {
|
| #define MAYBE_MultiThreadConsumerTest MultiThreadConsumerTest
|
| #endif
|
| // Test serial task servicing, as well as two parallel task servicing methods.
|
| -TEST_F(ConditionVariableTest, MAYBE_MultiThreadConsumerTest) {
|
| - const int kThreadCount = 10;
|
| - WorkQueue queue(kThreadCount); // Start the threads.
|
| -
|
| - const int kTaskCount = 10; // Number of tasks in each mini-test here.
|
| -
|
| - Time start_time; // Used to time task processing.
|
| -
|
| - {
|
| - base::AutoLock auto_lock(*queue.lock());
|
| - while (!queue.EveryIdWasAllocated())
|
| - queue.all_threads_have_ids()->Wait();
|
| - }
|
| -
|
| - // If threads aren't in a wait state, they may start to gobble up tasks in
|
| - // parallel, short-circuiting (breaking) this test.
|
| - queue.SpinUntilAllThreadsAreWaiting();
|
| -
|
| - {
|
| - // Since we have no tasks yet, all threads should be waiting by now.
|
| - base::AutoLock auto_lock(*queue.lock());
|
| - EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
|
| - EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
|
| - EXPECT_EQ(0, queue.task_count());
|
| - EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
|
| - EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
|
| - EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
|
| +TEST_F(ConditionVariableTest, MultiThreadConsumerTest) {
|
| + int current_test = 0;
|
| + while (++current_test <= 100) {
|
| + const int kThreadCount = 10;
|
| + WorkQueue queue(kThreadCount); // Start the threads.
|
|
|
| - // Set up to make each task include getting help from another worker, so
|
| - // so that the work gets done in paralell.
|
| - queue.ResetHistory();
|
| - queue.SetTaskCount(kTaskCount);
|
| - queue.SetWorkTime(kThirtyMs);
|
| - queue.SetAllowHelp(true);
|
| + const int kTaskCount = 10; // Number of tasks in each mini-test here.
|
|
|
| - start_time = Time::Now();
|
| - }
|
| + Time start_time; // Used to time task processing.
|
|
|
| - queue.work_is_available()->Signal(); // But each worker can signal another.
|
| - // Wait till we at least start to handle tasks (and we're not all waiting).
|
| - queue.SpinUntilTaskCountLessThan(kTaskCount);
|
| - // Wait to allow the all workers to get done.
|
| - queue.SpinUntilAllThreadsAreWaiting();
|
| + {
|
| + base::AutoLock auto_lock(*queue.lock());
|
| + while (!queue.EveryIdWasAllocated())
|
| + queue.all_threads_have_ids()->Wait();
|
| + }
|
|
|
| - {
|
| - // Wait until all work tasks have at least been assigned.
|
| - base::AutoLock auto_lock(*queue.lock());
|
| - while (queue.task_count())
|
| - queue.no_more_tasks()->Wait();
|
| + // If threads aren't in a wait state, they may start to gobble up tasks in
|
| + // parallel, short-circuiting (breaking) this test.
|
| + queue.SpinUntilAllThreadsAreWaiting();
|
|
|
| - // To avoid racy assumptions, we'll just assert that at least 2 threads
|
| - // did work. We know that the first worker should have gone to sleep, and
|
| - // hence a second worker should have gotten an assignment.
|
| - EXPECT_LE(2, queue.GetNumThreadsTakingAssignments());
|
| - EXPECT_EQ(kTaskCount, queue.GetNumberOfCompletedTasks());
|
| + {
|
| + // Since we have no tasks yet, all threads should be waiting by now.
|
| + base::AutoLock auto_lock(*queue.lock());
|
| + EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
|
| + EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
|
| + EXPECT_EQ(0, queue.task_count());
|
| + EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
|
| + EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
|
| + EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
|
| +
|
| + // Set up to make each task include getting help from another worker, so
|
| + // so that the work gets done in paralell.
|
| + queue.ResetHistory();
|
| + queue.SetTaskCount(kTaskCount);
|
| + queue.SetWorkTime(kThirtyMs);
|
| + queue.SetAllowHelp(true);
|
| +
|
| + start_time = Time::Now();
|
| + }
|
|
|
| - // Try to ask all workers to help, and only a few will do the work.
|
| - queue.ResetHistory();
|
| - queue.SetTaskCount(3);
|
| - queue.SetWorkTime(kThirtyMs);
|
| - queue.SetAllowHelp(false);
|
| - }
|
| - queue.work_is_available()->Broadcast(); // Make them all try.
|
| - // Wait till we at least start to handle tasks (and we're not all waiting).
|
| - queue.SpinUntilTaskCountLessThan(3);
|
| - // Wait to allow the 3 workers to get done.
|
| - queue.SpinUntilAllThreadsAreWaiting();
|
| + queue.work_is_available()->Signal(); // But each worker can signal another.
|
| + // Wait till we at least start to handle tasks (and we're not all waiting).
|
| + queue.SpinUntilTaskCountLessThan(kTaskCount);
|
| + // Wait to allow the all workers to get done.
|
| + queue.SpinUntilAllThreadsAreWaiting();
|
|
|
| - {
|
| - base::AutoLock auto_lock(*queue.lock());
|
| - EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
|
| - EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
|
| - EXPECT_EQ(0, queue.task_count());
|
| - EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
|
| - EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
|
| - EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
|
| -
|
| - // Set up to make each task get help from another worker.
|
| - queue.ResetHistory();
|
| - queue.SetTaskCount(3);
|
| - queue.SetWorkTime(kThirtyMs);
|
| - queue.SetAllowHelp(true); // Allow (unnecessary) help requests.
|
| - }
|
| - queue.work_is_available()->Broadcast(); // Signal all threads.
|
| - // Wait till we at least start to handle tasks (and we're not all waiting).
|
| - queue.SpinUntilTaskCountLessThan(3);
|
| - // Wait to allow the 3 workers to get done.
|
| - queue.SpinUntilAllThreadsAreWaiting();
|
| + {
|
| + // Wait until all work tasks have at least been assigned.
|
| + base::AutoLock auto_lock(*queue.lock());
|
| + while (queue.task_count())
|
| + queue.no_more_tasks()->Wait();
|
| +
|
| + // To avoid racy assumptions, we'll just assert that at least 2 threads
|
| + // did work. We know that the first worker should have gone to sleep, and
|
| + // hence a second worker should have gotten an assignment.
|
| + EXPECT_LE(2, queue.GetNumThreadsTakingAssignments());
|
| + EXPECT_EQ(kTaskCount, queue.GetNumberOfCompletedTasks());
|
| +
|
| + // Try to ask all workers to help, and only a few will do the work.
|
| + queue.ResetHistory();
|
| + queue.SetTaskCount(3);
|
| + queue.SetWorkTime(kThirtyMs);
|
| + queue.SetAllowHelp(false);
|
| + }
|
| + queue.work_is_available()->Broadcast(); // Make them all try.
|
| + // Wait till we at least start to handle tasks (and we're not all waiting).
|
| + queue.SpinUntilTaskCountLessThan(3);
|
| + // Wait to allow the 3 workers to get done.
|
| + queue.SpinUntilAllThreadsAreWaiting();
|
|
|
| - {
|
| - base::AutoLock auto_lock(*queue.lock());
|
| - EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
|
| - EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
|
| - EXPECT_EQ(0, queue.task_count());
|
| - EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
|
| - EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
|
| - EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
|
| + {
|
| + base::AutoLock auto_lock(*queue.lock());
|
| + EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
|
| + EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
|
| + EXPECT_EQ(0, queue.task_count());
|
| + EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
|
| + EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
|
| + EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
|
| +
|
| + // Set up to make each task get help from another worker.
|
| + queue.ResetHistory();
|
| + queue.SetTaskCount(3);
|
| + queue.SetWorkTime(kThirtyMs);
|
| + queue.SetAllowHelp(true); // Allow (unnecessary) help requests.
|
| + }
|
| + queue.work_is_available()->Broadcast(); // Signal all threads.
|
| + // Wait till we at least start to handle tasks (and we're not all waiting).
|
| + queue.SpinUntilTaskCountLessThan(3);
|
| + // Wait to allow the 3 workers to get done.
|
| + queue.SpinUntilAllThreadsAreWaiting();
|
|
|
| - // Set up to make each task get help from another worker.
|
| - queue.ResetHistory();
|
| - queue.SetTaskCount(20); // 2 tasks per thread.
|
| - queue.SetWorkTime(kThirtyMs);
|
| - queue.SetAllowHelp(true);
|
| - }
|
| - queue.work_is_available()->Signal(); // But each worker can signal another.
|
| - // Wait till we at least start to handle tasks (and we're not all waiting).
|
| - queue.SpinUntilTaskCountLessThan(20);
|
| - // Wait to allow the 10 workers to get done.
|
| - queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
|
| + {
|
| + base::AutoLock auto_lock(*queue.lock());
|
| + EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
|
| + EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
|
| + EXPECT_EQ(0, queue.task_count());
|
| + EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
|
| + EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
|
| + EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
|
| +
|
| + // Set up to make each task get help from another worker.
|
| + queue.ResetHistory();
|
| + queue.SetTaskCount(20); // 2 tasks per thread.
|
| + queue.SetWorkTime(kThirtyMs);
|
| + queue.SetAllowHelp(true);
|
| + }
|
| + queue.work_is_available()->Signal(); // But each worker can signal another.
|
| + // Wait till we at least start to handle tasks (and we're not all waiting).
|
| + queue.SpinUntilTaskCountLessThan(20);
|
| + // Wait to allow the 10 workers to get done.
|
| + queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
|
|
|
| - {
|
| - base::AutoLock auto_lock(*queue.lock());
|
| - EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
|
| - EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
|
| - EXPECT_EQ(0, queue.task_count());
|
| - EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
|
| + {
|
| + base::AutoLock auto_lock(*queue.lock());
|
| + EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
|
| + EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
|
| + EXPECT_EQ(0, queue.task_count());
|
| + EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
|
| +
|
| + // Same as last test, but with Broadcast().
|
| + queue.ResetHistory();
|
| + queue.SetTaskCount(20); // 2 tasks per thread.
|
| + queue.SetWorkTime(kThirtyMs);
|
| + queue.SetAllowHelp(true);
|
| + }
|
| + queue.work_is_available()->Broadcast();
|
| + // Wait till we at least start to handle tasks (and we're not all waiting).
|
| + queue.SpinUntilTaskCountLessThan(20);
|
| + // Wait to allow the 10 workers to get done.
|
| + queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
|
|
|
| - // Same as last test, but with Broadcast().
|
| - queue.ResetHistory();
|
| - queue.SetTaskCount(20); // 2 tasks per thread.
|
| - queue.SetWorkTime(kThirtyMs);
|
| - queue.SetAllowHelp(true);
|
| - }
|
| - queue.work_is_available()->Broadcast();
|
| - // Wait till we at least start to handle tasks (and we're not all waiting).
|
| - queue.SpinUntilTaskCountLessThan(20);
|
| - // Wait to allow the 10 workers to get done.
|
| - queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
|
| + {
|
| + base::AutoLock auto_lock(*queue.lock());
|
| + EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
|
| + EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
|
| + EXPECT_EQ(0, queue.task_count());
|
| + EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
|
|
|
| - {
|
| - base::AutoLock auto_lock(*queue.lock());
|
| - EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
|
| - EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
|
| - EXPECT_EQ(0, queue.task_count());
|
| - EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
|
| + queue.SetShutdown();
|
| + }
|
| + queue.work_is_available()->Broadcast(); // Force check for shutdown.
|
|
|
| - queue.SetShutdown();
|
| + SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(
|
| + TimeDelta::FromMinutes(1), queue.ThreadSafeCheckShutdown(kThreadCount));
|
| }
|
| - queue.work_is_available()->Broadcast(); // Force check for shutdown.
|
| -
|
| - SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
|
| - queue.ThreadSafeCheckShutdown(kThreadCount));
|
| }
|
|
|
| TEST_F(ConditionVariableTest, LargeFastTaskTest) {
|
|
|