1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be
3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file.
4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Multi-threaded tests of ConditionVariable class.
6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <time.h>
8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <algorithm>
9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <vector>
10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/bind.h"
12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/location.h"
13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h"
14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/scoped_ptr.h"
15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/single_thread_task_runner.h"
16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/synchronization/condition_variable.h"
17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/synchronization/lock.h"
18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/synchronization/spin_wait.h"
19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/platform_thread.h"
20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/thread.h"
21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/thread_collision_warner.h"
22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/time/time.h"
23cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "build/build_config.h"
24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "testing/gtest/include/gtest/gtest.h"
25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "testing/platform_test.h"
26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base {
28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace {
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Define our test class, with several common variables.
32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass ConditionVariableTest : public PlatformTest {
35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta kZeroMs;
37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta kTenMs;
38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta kThirtyMs;
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta kFortyFiveMs;
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta kSixtyMs;
41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta kOneHundredMs;
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariableTest()
44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      : kZeroMs(TimeDelta::FromMilliseconds(0)),
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        kTenMs(TimeDelta::FromMilliseconds(10)),
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        kThirtyMs(TimeDelta::FromMilliseconds(30)),
47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        kFortyFiveMs(TimeDelta::FromMilliseconds(45)),
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        kSixtyMs(TimeDelta::FromMilliseconds(60)),
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        kOneHundredMs(TimeDelta::FromMilliseconds(100)) {
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Define a class that will control activities an several multi-threaded tests.
55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The general structure of multi-threaded tests is that a test case will
56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// construct an instance of a WorkQueue.  The WorkQueue will spin up some
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// threads and control them throughout their lifetime, as well as maintaining
58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// a central repository of the work thread's activity.  Finally, the WorkQueue
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// will command the the worker threads to terminate.  At that point, the test
60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// cases will validate that the WorkQueue has records showing that the desired
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// activities were performed.
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Callers are responsible for synchronizing access to the following class.
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The WorkQueue::lock_, as accessed via WorkQueue::lock(), should be used for
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// all synchronized access.
67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass WorkQueue : public PlatformThread::Delegate {
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  explicit WorkQueue(int thread_count);
70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~WorkQueue() override;
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // PlatformThread::Delegate interface.
73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void ThreadMain() override;
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  //----------------------------------------------------------------------------
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Worker threads only call the following methods.
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // They should use the lock to get exclusive access.
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int GetThreadId();  // Get an ID assigned to a thread..
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool EveryIdWasAllocated() const;  // Indicates that all IDs were handed out.
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeDelta GetAnAssignment(int thread_id);  // Get a work task duration.
81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void WorkIsCompleted(int thread_id);
82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int task_count() const;
84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool allow_help_requests() const;  // Workers can signal more workers.
85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool shutdown() const;  // Check if shutdown has been requested.
86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void thread_shutting_down();
88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  //----------------------------------------------------------------------------
91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Worker threads can call them but not needed to acquire a lock.
92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Lock* lock();
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable* work_is_available();
95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable* all_threads_have_ids();
96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable* no_more_tasks();
97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  //----------------------------------------------------------------------------
99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // The rest of the methods are for use by the controlling master thread (the
100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // test case code).
101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void ResetHistory();
102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int GetMinCompletionsByWorkerThread() const;
103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int GetMaxCompletionsByWorkerThread() const;
104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int GetNumThreadsTakingAssignments() const;
105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int GetNumThreadsCompletingTasks() const;
106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int GetNumberOfCompletedTasks() const;
107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void SetWorkTime(TimeDelta delay);
109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void SetTaskCount(int count);
110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void SetAllowHelp(bool allow);
111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // The following must be called without locking, and will spin wait until the
113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // threads are all in a wait state.
114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void SpinUntilAllThreadsAreWaiting();
115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void SpinUntilTaskCountLessThan(int task_count);
116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Caller must acquire lock before calling.
118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void SetShutdown();
119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Compares the |shutdown_task_count_| to the |thread_count| and returns true
121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // if they are equal.  This check will acquire the |lock_| so the caller
122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // should not hold the lock when calling this method.
123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool ThreadSafeCheckShutdown(int thread_count);
124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Both worker threads and controller use the following to synchronize.
127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Lock lock_;
128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable work_is_available_;  // To tell threads there is work.
129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Conditions to notify the controlling process (if it is interested).
131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable all_threads_have_ids_;  // All threads are running.
132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable no_more_tasks_;  // Task count is zero.
133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const int thread_count_;
135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int waiting_thread_count_;
136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  scoped_ptr<PlatformThreadHandle[]> thread_handles_;
137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  std::vector<int> assignment_history_;  // Number of assignment per worker.
138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  std::vector<int> completion_history_;  // Number of completions per worker.
139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int thread_started_counter_;  // Used to issue unique id to workers.
140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int shutdown_task_count_;  // Number of tasks told to shutdown
141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int task_count_;  // Number of assignment tasks waiting to be processed.
142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeDelta worker_delay_;  // Time each task takes to complete.
143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool allow_help_requests_;  // Workers can signal more workers.
144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool shutdown_;  // Set when threads need to terminate.
145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_MUTEX(locked_methods_);
147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The next section contains the actual tests.
151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(ConditionVariableTest, StartupShutdownTest) {
154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Lock lock;
155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // First try trivial startup/shutdown.
157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    ConditionVariable cv1(&lock);
159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }  // Call for cv1 destruction.
160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Exercise with at least a few waits.
162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable cv(&lock);
163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock.Acquire();
165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  cv.TimedWait(kTenMs);  // Wait for 10 ms.
166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  cv.TimedWait(kTenMs);  // Wait for 10 ms.
167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock.Release();
168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock.Acquire();
170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  cv.TimedWait(kTenMs);  // Wait for 10 ms.
171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  cv.TimedWait(kTenMs);  // Wait for 10 ms.
172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  cv.TimedWait(kTenMs);  // Wait for 10 ms.
173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock.Release();
174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // Call for cv destruction.
175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(ConditionVariableTest, TimeoutTest) {
177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Lock lock;
178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable cv(&lock);
179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock.Acquire();
180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeTicks start = TimeTicks::Now();
182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta WAIT_TIME = TimeDelta::FromMilliseconds(300);
183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Allow for clocking rate granularity.
184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta FUDGE_TIME = TimeDelta::FromMilliseconds(50);
185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  cv.TimedWait(WAIT_TIME + FUDGE_TIME);
187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeDelta duration = TimeTicks::Now() - start;
188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // We can't use EXPECT_GE here as the TimeDelta class does not support the
189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // required stream conversion.
190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(duration >= WAIT_TIME);
191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock.Release();
193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_POSIX)
196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst int kDiscontinuitySeconds = 2;
197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid BackInTime(Lock* lock) {
199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  AutoLock auto_lock(*lock);
200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  timeval tv;
202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  gettimeofday(&tv, NULL);
203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  tv.tv_sec -= kDiscontinuitySeconds;
204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  settimeofday(&tv, NULL);
205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Tests that TimedWait ignores changes to the system clock.
208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Test is disabled by default, because it needs to run as root to muck with the
209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// system clock.
210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// http://crbug.com/293736
211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(ConditionVariableTest, DISABLED_TimeoutAcrossSetTimeOfDay) {
212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  timeval tv;
213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  gettimeofday(&tv, NULL);
214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  tv.tv_sec += kDiscontinuitySeconds;
215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (settimeofday(&tv, NULL) < 0) {
216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    PLOG(ERROR) << "Could not set time of day. Run as root?";
217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return;
218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Lock lock;
221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable cv(&lock);
222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock.Acquire();
223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Thread thread("Helper");
225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  thread.Start();
226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  thread.task_runner()->PostTask(FROM_HERE, base::Bind(&BackInTime, &lock));
227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeTicks start = TimeTicks::Now();
229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta kWaitTime = TimeDelta::FromMilliseconds(300);
230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Allow for clocking rate granularity.
231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const TimeDelta kFudgeTime = TimeDelta::FromMilliseconds(50);
232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  cv.TimedWait(kWaitTime + kFudgeTime);
234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TimeDelta duration = TimeTicks::Now() - start;
235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  thread.Stop();
237b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // We can't use EXPECT_GE here as the TimeDelta class does not support the
238b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // required stream conversion.
239b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(duration >= kWaitTime);
240b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(duration <= TimeDelta::FromSeconds(kDiscontinuitySeconds));
241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock.Release();
243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Suddenly got flaky on Win, see http://crbug.com/10607 (starting at
248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// comment #15).
249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_WIN)
250b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define MAYBE_MultiThreadConsumerTest DISABLED_MultiThreadConsumerTest
251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else
252b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define MAYBE_MultiThreadConsumerTest MultiThreadConsumerTest
253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Test serial task servicing, as well as two parallel task servicing methods.
255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(ConditionVariableTest, MAYBE_MultiThreadConsumerTest) {
256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const int kThreadCount = 10;
257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WorkQueue queue(kThreadCount);  // Start the threads.
258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const int kTaskCount = 10;  // Number of tasks in each mini-test here.
260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Time start_time;  // Used to time task processing.
262b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
263b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
264b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
265b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    while (!queue.EveryIdWasAllocated())
266b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      queue.all_threads_have_ids()->Wait();
267b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
268b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
269b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // If threads aren't in a wait state, they may start to gobble up tasks in
270b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // parallel, short-circuiting (breaking) this test.
271b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();
272b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
273b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
274b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Since we have no tasks yet, all threads should be waiting by now.
275b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
276b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
277b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
278b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.task_count());
279b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
280b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
281b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
282b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
283b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Set up to make each task include getting help from another worker, so
284b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // so that the work gets done in paralell.
285b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.ResetHistory();
286b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetTaskCount(kTaskCount);
287b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetWorkTime(kThirtyMs);
288b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetAllowHelp(true);
289b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
290b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    start_time = Time::Now();
291b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
292b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
293b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Signal();  // But each worker can signal another.
294b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait till we at least start to handle tasks (and we're not all waiting).
295b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilTaskCountLessThan(kTaskCount);
296b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait to allow the all workers to get done.
297b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();
298b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
299b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
300b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Wait until all work tasks have at least been assigned.
301b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
302b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    while (queue.task_count())
303b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      queue.no_more_tasks()->Wait();
304b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
305b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // To avoid racy assumptions, we'll just assert that at least 2 threads
306b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // did work.  We know that the first worker should have gone to sleep, and
307b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // hence a second worker should have gotten an assignment.
308b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_LE(2, queue.GetNumThreadsTakingAssignments());
309b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(kTaskCount, queue.GetNumberOfCompletedTasks());
310b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
311b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Try to ask all workers to help, and only a few will do the work.
312b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.ResetHistory();
313b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetTaskCount(3);
314b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetWorkTime(kThirtyMs);
315b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetAllowHelp(false);
316b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
317b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Broadcast();  // Make them all try.
318b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait till we at least start to handle tasks (and we're not all waiting).
319b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilTaskCountLessThan(3);
320b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait to allow the 3 workers to get done.
321b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();
322b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
323b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
324b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
325b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
326b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
327b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.task_count());
328b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
329b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
330b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
331b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
332b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Set up to make each task get help from another worker.
333b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.ResetHistory();
334b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetTaskCount(3);
335b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetWorkTime(kThirtyMs);
336b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetAllowHelp(true);  // Allow (unnecessary) help requests.
337b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
338b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Broadcast();  // Signal all threads.
339b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait till we at least start to handle tasks (and we're not all waiting).
340b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilTaskCountLessThan(3);
341b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait to allow the 3 workers to get done.
342b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();
343b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
344b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
345b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
346b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
347b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
348b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.task_count());
349b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
350b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
351b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
352b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
353b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Set up to make each task get help from another worker.
354b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.ResetHistory();
355b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetTaskCount(20);  // 2 tasks per thread.
356b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetWorkTime(kThirtyMs);
357b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetAllowHelp(true);
358b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
359b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Signal();  // But each worker can signal another.
360b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait till we at least start to handle tasks (and we're not all waiting).
361b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilTaskCountLessThan(20);
362b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait to allow the 10 workers to get done.
363b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();  // Should take about 60 ms.
364b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
365b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
366b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
367b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
368b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
369b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.task_count());
370b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
371b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
372b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Same as last test, but with Broadcast().
373b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.ResetHistory();
374b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetTaskCount(20);  // 2 tasks per thread.
375b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetWorkTime(kThirtyMs);
376b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetAllowHelp(true);
377b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
378b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Broadcast();
379b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait till we at least start to handle tasks (and we're not all waiting).
380b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilTaskCountLessThan(20);
381b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait to allow the 10 workers to get done.
382b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();  // Should take about 60 ms.
383b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
384b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
385b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
386b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
387b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
388b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.task_count());
389b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
390b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
391b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetShutdown();
392b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
393b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Broadcast();  // Force check for shutdown.
394b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
395b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
396b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                   queue.ThreadSafeCheckShutdown(kThreadCount));
397b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
398b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
399b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(ConditionVariableTest, LargeFastTaskTest) {
400b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  const int kThreadCount = 200;
401b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WorkQueue queue(kThreadCount);  // Start the threads.
402b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
403b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Lock private_lock;  // Used locally for master to wait.
404b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  base::AutoLock private_held_lock(private_lock);
405b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConditionVariable private_cv(&private_lock);
406b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
407b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
408b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
409b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    while (!queue.EveryIdWasAllocated())
410b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      queue.all_threads_have_ids()->Wait();
411b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
412b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
413b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait a bit more to allow threads to reach their wait state.
414b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();
415b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
416b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
417b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Since we have no tasks, all threads should be waiting by now.
418b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
419b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
420b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
421b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.task_count());
422b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
423b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
424b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
425b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
426b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Set up to make all workers do (an average of) 20 tasks.
427b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.ResetHistory();
428b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetTaskCount(20 * kThreadCount);
429b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetWorkTime(kFortyFiveMs);
430b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetAllowHelp(false);
431b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
432b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Broadcast();  // Start up all threads.
433b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait until we've handed out all tasks.
434b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
435b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
436b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    while (queue.task_count() != 0)
437b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      queue.no_more_tasks()->Wait();
438b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
439b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
440b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait till the last of the tasks complete.
441b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();
442b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
443b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
444b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // With Broadcast(), every thread should have participated.
445b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // but with racing.. they may not all have done equal numbers of tasks.
446b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
447b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(kThreadCount, queue.GetNumThreadsTakingAssignments());
448b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(kThreadCount, queue.GetNumThreadsCompletingTasks());
449b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.task_count());
450b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_LE(20, queue.GetMaxCompletionsByWorkerThread());
451b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(20 * kThreadCount, queue.GetNumberOfCompletedTasks());
452b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
453b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Set up to make all workers do (an average of) 4 tasks.
454b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.ResetHistory();
455b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetTaskCount(kThreadCount * 4);
456b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetWorkTime(kFortyFiveMs);
457b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetAllowHelp(true);  // Might outperform Broadcast().
458b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
459b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Signal();  // Start up one thread.
460b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
461b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait until we've handed out all tasks
462b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
463b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
464b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    while (queue.task_count() != 0)
465b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      queue.no_more_tasks()->Wait();
466b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
467b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
468b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait till the last of the tasks complete.
469b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.SpinUntilAllThreadsAreWaiting();
470b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
471b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
472b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // With Signal(), every thread should have participated.
473b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // but with racing.. they may not all have done four tasks.
474b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(*queue.lock());
475b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(kThreadCount, queue.GetNumThreadsTakingAssignments());
476b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(kThreadCount, queue.GetNumThreadsCompletingTasks());
477b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, queue.task_count());
478b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_LE(4, queue.GetMaxCompletionsByWorkerThread());
479b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(4 * kThreadCount, queue.GetNumberOfCompletedTasks());
480b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
481b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    queue.SetShutdown();
482b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
483b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  queue.work_is_available()->Broadcast();  // Force check for shutdown.
484b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
485b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Wait for shutdowns to complete.
486b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
487b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                   queue.ThreadSafeCheckShutdown(kThreadCount));
488b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
489b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
490b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
491b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Finally we provide the implementation for the methods in the WorkQueue class.
492b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
493b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
494b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratWorkQueue::WorkQueue(int thread_count)
495b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  : lock_(),
496b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    work_is_available_(&lock_),
497b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    all_threads_have_ids_(&lock_),
498b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    no_more_tasks_(&lock_),
499b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    thread_count_(thread_count),
500b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    waiting_thread_count_(0),
501b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    thread_handles_(new PlatformThreadHandle[thread_count]),
502b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    assignment_history_(thread_count),
503b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion_history_(thread_count),
504b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    thread_started_counter_(0),
505b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    shutdown_task_count_(0),
506b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    task_count_(0),
507b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    allow_help_requests_(false),
508b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    shutdown_(false) {
509b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_GE(thread_count_, 1);
510b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ResetHistory();
511b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  SetTaskCount(0);
512b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  SetWorkTime(TimeDelta::FromMilliseconds(30));
513b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
514b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (int i = 0; i < thread_count_; ++i) {
515b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    PlatformThreadHandle pth;
516b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_TRUE(PlatformThread::Create(0, this, &pth));
517b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    thread_handles_[i] = pth;
518b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
519b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
520b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
521b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratWorkQueue::~WorkQueue() {
522b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
523b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(lock_);
524b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    SetShutdown();
525b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
526b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  work_is_available_.Broadcast();  // Tell them all to terminate.
527b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
528b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (int i = 0; i < thread_count_; ++i) {
529b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    PlatformThread::Join(thread_handles_[i]);
530b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
531b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(0, waiting_thread_count_);
532b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
533b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
534b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint WorkQueue::GetThreadId() {
535b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
536b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(!EveryIdWasAllocated());
537b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return thread_started_counter_++;  // Give out Unique IDs.
538b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
539b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
540b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool WorkQueue::EveryIdWasAllocated() const {
541b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
542b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return thread_count_ == thread_started_counter_;
543b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
544b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
545b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTimeDelta WorkQueue::GetAnAssignment(int thread_id) {
546b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
547b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK_LT(0, task_count_);
548b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  assignment_history_[thread_id]++;
549b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (0 == --task_count_) {
550b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    no_more_tasks_.Signal();
551b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
552b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return worker_delay_;
553b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
554b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
555b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::WorkIsCompleted(int thread_id) {
556b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
557b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  completion_history_[thread_id]++;
558b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
559b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
560b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint WorkQueue::task_count() const {
561b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
562b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return task_count_;
563b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
564b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
565b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool WorkQueue::allow_help_requests() const {
566b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
567b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return allow_help_requests_;
568b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
569b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
570b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool WorkQueue::shutdown() const {
571b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock_.AssertAcquired();
572b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
573b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return shutdown_;
574b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
575b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
576b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Because this method is called from the test's main thread we need to actually
577b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// take the lock.  Threads will call the thread_shutting_down() method with the
578b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// lock already acquired.
579b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool WorkQueue::ThreadSafeCheckShutdown(int thread_count) {
580b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool all_shutdown;
581b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  base::AutoLock auto_lock(lock_);
582b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
583b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Declare in scope so DFAKE is guranteed to be destroyed before AutoLock.
584b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
585b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    all_shutdown = (shutdown_task_count_ == thread_count);
586b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
587b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return all_shutdown;
588b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
589b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
590b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::thread_shutting_down() {
591b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock_.AssertAcquired();
592b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
593b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  shutdown_task_count_++;
594b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
595b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
596b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratLock* WorkQueue::lock() {
597b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return &lock_;
598b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
599b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
600b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratConditionVariable* WorkQueue::work_is_available() {
601b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return &work_is_available_;
602b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
603b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
604b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratConditionVariable* WorkQueue::all_threads_have_ids() {
605b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return &all_threads_have_ids_;
606b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
607b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
608b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratConditionVariable* WorkQueue::no_more_tasks() {
609b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return &no_more_tasks_;
610b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
611b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
612b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::ResetHistory() {
613b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (int i = 0; i < thread_count_; ++i) {
614b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    assignment_history_[i] = 0;
615b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion_history_[i] = 0;
616b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
617b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
618b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
619b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint WorkQueue::GetMinCompletionsByWorkerThread() const {
620b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int minumum = completion_history_[0];
621b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (int i = 0; i < thread_count_; ++i)
622b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    minumum = std::min(minumum, completion_history_[i]);
623b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return minumum;
624b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
625b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
626b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint WorkQueue::GetMaxCompletionsByWorkerThread() const {
627b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int maximum = completion_history_[0];
628b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (int i = 0; i < thread_count_; ++i)
629b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    maximum = std::max(maximum, completion_history_[i]);
630b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return maximum;
631b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
632b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
633b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint WorkQueue::GetNumThreadsTakingAssignments() const {
634b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int count = 0;
635b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (int i = 0; i < thread_count_; ++i)
636b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (assignment_history_[i])
637b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      count++;
638b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return count;
639b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
640b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
641b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint WorkQueue::GetNumThreadsCompletingTasks() const {
642b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int count = 0;
643b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (int i = 0; i < thread_count_; ++i)
644b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (completion_history_[i])
645b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      count++;
646b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return count;
647b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
648b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
649b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint WorkQueue::GetNumberOfCompletedTasks() const {
650b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int total = 0;
651b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (int i = 0; i < thread_count_; ++i)
652b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    total += completion_history_[i];
653b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return total;
654b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
655b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
656b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::SetWorkTime(TimeDelta delay) {
657b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  worker_delay_ = delay;
658b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
659b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
660b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::SetTaskCount(int count) {
661b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  task_count_ = count;
662b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
663b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
664b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::SetAllowHelp(bool allow) {
665b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  allow_help_requests_ = allow;
666b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
667b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
668b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::SetShutdown() {
669b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  lock_.AssertAcquired();
670b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  shutdown_ = true;
671b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
672b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
673b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::SpinUntilAllThreadsAreWaiting() {
674b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  while (true) {
675b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    {
676b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      base::AutoLock auto_lock(lock_);
677b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      if (waiting_thread_count_ == thread_count_)
678b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        break;
679b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }
680b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
681b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
682b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
683b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
684b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::SpinUntilTaskCountLessThan(int task_count) {
685b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  while (true) {
686b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    {
687b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      base::AutoLock auto_lock(lock_);
688b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      if (task_count_ < task_count)
689b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        break;
690b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }
691b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
692b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
693b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
694b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
695b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
696b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
697b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Define the standard worker task. Several tests will spin out many of these
698b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// threads.
699b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------
700b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
701b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The multithread tests involve several threads with a task to perform as
702b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// directed by an instance of the class WorkQueue.
703b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The task is to:
704b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// a) Check to see if there are more tasks (there is a task counter).
705b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    a1) Wait on condition variable if there are no tasks currently.
706b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// b) Call a function to see what should be done.
707b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// c) Do some computation based on the number of milliseconds returned in (b).
708b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// d) go back to (a).
709b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
710b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// WorkQueue::ThreadMain() implements the above task for all threads.
711b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// It calls the controlling object to tell the creator about progress, and to
712b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// ask about tasks.
713b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
714b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid WorkQueue::ThreadMain() {
715b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int thread_id;
716b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
717b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::AutoLock auto_lock(lock_);
718b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    thread_id = GetThreadId();
719b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (EveryIdWasAllocated())
720b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      all_threads_have_ids()->Signal();  // Tell creator we're ready.
721b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
722b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
723b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Lock private_lock;  // Used to waste time on "our work".
724b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  while (1) {  // This is the main consumer loop.
725b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    TimeDelta work_time;
726b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    bool could_use_help;
727b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    {
728b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      base::AutoLock auto_lock(lock_);
729b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      while (0 == task_count() && !shutdown()) {
730b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        ++waiting_thread_count_;
731b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        work_is_available()->Wait();
732b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        --waiting_thread_count_;
733b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      }
734b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      if (shutdown()) {
735b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        // Ack the notification of a shutdown message back to the controller.
736b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        thread_shutting_down();
737b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        return;  // Terminate.
738b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      }
739b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      // Get our task duration from the queue.
740b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      work_time = GetAnAssignment(thread_id);
741b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      could_use_help = (task_count() > 0) && allow_help_requests();
742b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }  // Release lock
743b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
744b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Do work (outside of locked region.
745b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (could_use_help)
746b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      work_is_available()->Signal();  // Get help from other threads.
747b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
748b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (work_time > TimeDelta::FromMilliseconds(0)) {
749b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      // We could just sleep(), but we'll instead further exercise the
750b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      // condition variable class, and do a timed wait.
751b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      base::AutoLock auto_lock(private_lock);
752b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ConditionVariable private_cv(&private_lock);
753b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      private_cv.TimedWait(work_time);  // Unsynchronized waiting.
754b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }
755b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
756b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    {
757b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      base::AutoLock auto_lock(lock_);
758b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      // Send notification that we completed our "work."
759b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      WorkIsCompleted(thread_id);
760b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }
761b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
762b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
763b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
764b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace
765b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
766b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
767