Page Speed Optimization Libraries  1.13.35.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
condvar_test_base.h
Go to the documentation of this file.
1 // Copyright 2011 Google Inc.
16 
17 #ifndef PAGESPEED_KERNEL_THREAD_CONDVAR_TEST_BASE_H_
18 #define PAGESPEED_KERNEL_THREAD_CONDVAR_TEST_BASE_H_
19 
21 
22 #include "base/logging.h"
28 
29 namespace net_instaweb {
30 
31 class CondvarTestBase : public testing::Test {
32  protected:
33  typedef void (ThreadSystem::Condvar::*SignalMethod)();
34 
36  : mutex_(NULL),
37  startup_condvar_(NULL),
38  condvar_(NULL),
39  ready_to_start_(false),
40  iters_(0),
41  current_iter_(0),
42  signal_method_(&ThreadSystem::Condvar::Signal),
43  wait_after_signal_(false),
44  helper_increments_(0),
45  init_called_(false) {
46  }
47 
51  ThreadSystem::Condvar* startup_condvar,
52  ThreadSystem::Condvar* condvar) {
53  CHECK(!init_called_);
54  mutex_ = mutex;
55  startup_condvar_ = startup_condvar;
56  condvar_ = condvar;
57  init_called_ = true;
58  }
59 
60  static void* HelperThread(void* data) {
61  CondvarTestBase* test = static_cast<CondvarTestBase*>(data);
62  test->HelperThreadMethod();
63  return NULL;
64  }
65 
69  virtual void CreateHelper() = 0;
70 
73  virtual void FinishHelper() = 0;
74 
75  void StartHelper() {
76  CHECK(init_called_);
77  CreateHelper();
78  {
79  ScopedMutex lock(mutex_);
80  ready_to_start_ = true;
81  startup_condvar_->Signal();
82  }
83  }
84 
85  virtual void HelperThreadMethod() {
86  {
87  ScopedMutex lock(mutex_);
88  while (!ready_to_start_) {
89  startup_condvar_->Wait();
90  }
91  }
92  while (true) {
93  ScopedMutex lock(mutex_);
96  int iter = current_iter_ + 1;
97  if (iter > iters_) {
98  return;
99  }
100  ++helper_increments_;
101  current_iter_ = iter;
102  (condvar_->*signal_method_)();
103  while (wait_after_signal_ && current_iter_ == iter) {
104  condvar_->Wait();
105  }
106  }
107  }
108 
110 
112  void StartupTest() {
113  StartHelper();
114  EXPECT_TRUE(ready_to_start_);
115  FinishHelper();
116  EXPECT_EQ(helper_increments_, 0);
117  }
118 
122  iters_ = 10;
123  StartHelper();
124  EXPECT_TRUE(ready_to_start_);
125  FinishHelper();
126  EXPECT_EQ(helper_increments_, 10);
127  }
128 
131  void PingPongTest() {
132  iters_ = 10;
133  wait_after_signal_ = true;
134  StartHelper();
135  int local_increments = 0;
136  while (true) {
137  ScopedMutex lock(mutex_);
138  while ((current_iter_ % 2) == 0 && current_iter_ < iters_) {
139  condvar_->Wait();
140  }
143  if (current_iter_ == iters_) {
144  break;
145  }
146  ++current_iter_;
147  ++local_increments;
148  condvar_->Signal();
149  }
150  EXPECT_EQ(local_increments, 5);
151  FinishHelper();
152  EXPECT_EQ(helper_increments_, 5);
153  }
154 
156  void TimeoutTest() {
157  iters_ = 0;
158  StartHelper();
159  {
160  ScopedMutex lock(mutex_);
161  condvar_->TimedWait(10);
162  }
163  FinishHelper();
164  }
165 
167  void LongTimeoutTest(int wait_ms) {
168  iters_ = 0;
169  StartHelper();
170  int64 start_ms = timer()->NowMs();
171  {
172  ScopedMutex lock(mutex_);
173  condvar_->TimedWait(wait_ms);
174  }
175  int64 end_ms = timer()->NowMs();
176 
179  EXPECT_LE(wait_ms, end_ms - start_ms);
180  FinishHelper();
181  }
182 
187  iters_ = 10;
188  wait_after_signal_ = true;
189  StartHelper();
190  int local_increments = 0;
191  while (true) {
192  ScopedMutex lock(mutex_);
193  if ((current_iter_ % 2) == 0) {
194  condvar_->TimedWait(1);
195  }
200  if (current_iter_ > iters_) {
201  break;
202  }
203  ++current_iter_;
204  ++local_increments;
205  condvar_->Signal();
206  }
207  FinishHelper();
208  EXPECT_LE(6, local_increments);
209  EXPECT_GE(5, helper_increments_);
210  EXPECT_EQ(11, local_increments + helper_increments_);
211  }
212 
213  virtual Timer* timer() = 0;
214 
216  ThreadSystem::Condvar* startup_condvar_;
217  ThreadSystem::Condvar* condvar_;
218  bool ready_to_start_;
219  int iters_;
220  int current_iter_;
221  SignalMethod signal_method_;
222  bool wait_after_signal_;
223  int helper_increments_;
224  bool init_called_;
225 
226  private:
227 
228 };
229 
230 }
231 
232 #endif
void PingPongTest()
Definition: condvar_test_base.h:131
Definition: condvar.h:27
virtual int64 NowMs() const
Returns number of milliseconds since 1970.
virtual void CreateHelper()=0
void TimeoutTest()
Make sure that TimedWait eventually progresses in the absence of a signal.
Definition: condvar_test_base.h:156
void Init(ThreadSystem::CondvarCapableMutex *mutex, ThreadSystem::Condvar *startup_condvar, ThreadSystem::Condvar *condvar)
Definition: condvar_test_base.h:50
virtual void TimedWait(int64 timeout_ms)=0
#define ScopedMutex(x)
Definition: abstract_mutex.h:69
Definition: condvar_test_base.h:31
void LongTimeoutTest(int wait_ms)
Make sure that a long timeout doesn't exit too early.
Definition: condvar_test_base.h:167
Helper class for lexically scoped mutexing.
Definition: abstract_mutex.h:46
virtual void FinishHelper()=0
void StartupTest()
Below are the common tests that should be run by every client.
Definition: condvar_test_base.h:112
virtual void HelperThreadMethod()
Definition: condvar_test_base.h:85
void TimeoutPingPongTest()
Definition: condvar_test_base.h:186
Timer interface, made virtual so it can be mocked for tests.
Definition: timer.h:27
void BlindSignalsTest()
Definition: condvar_test_base.h:121