Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / system_wrappers / source / condition_variable_unittest.cc
1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11 #include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
12
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
15 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
16 #include "webrtc/system_wrappers/interface/trace.h"
17
18 namespace webrtc {
19
20 namespace {
21
22 const int kLongWaitMs = 100 * 1000; // A long time in testing terms
23 const int kShortWaitMs = 2 * 1000; // Long enough for process switches to happen
24
25 // A Baton is one possible control structure one can build using
26 // conditional variables.
27 // A Baton is always held by one and only one active thread - unlike
28 // a lock, it can never be free.
29 // One can pass it or grab it - both calls have timeouts.
30 // Note - a production tool would guard against passing it without
31 // grabbing it first. This one is for testing, so it doesn't.
32 class Baton {
33  public:
34   Baton()
35     : giver_sect_(CriticalSectionWrapper::CreateCriticalSection()),
36       crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
37       cond_var_(ConditionVariableWrapper::CreateConditionVariable()),
38       being_passed_(false),
39       pass_count_(0) {
40   }
41
42   ~Baton() {
43     delete giver_sect_;
44     delete crit_sect_;
45     delete cond_var_;
46   }
47
48   // Pass the baton. Returns false if baton is not picked up in |max_msecs|.
49   // Only one process can pass at the same time; this property is
50   // ensured by the |giver_sect_| lock.
51   bool Pass(uint32_t max_msecs) {
52     CriticalSectionScoped cs_giver(giver_sect_);
53     CriticalSectionScoped cs(crit_sect_);
54     SignalBatonAvailable();
55     const bool result = TakeBatonIfStillFree(max_msecs);
56     if (result) {
57       ++pass_count_;
58     }
59     return result;
60   }
61
62   // Grab the baton. Returns false if baton is not passed.
63   bool Grab(uint32_t max_msecs) {
64     CriticalSectionScoped cs(crit_sect_);
65     return WaitUntilBatonOffered(max_msecs);
66   }
67
68   int PassCount() {
69     // We don't allow polling PassCount() during a Pass()-call since there is
70     // no guarantee that |pass_count_| is incremented until the Pass()-call
71     // finishes. I.e. the Grab()-call may finish before |pass_count_| has been
72     // incremented.
73     // Thus, this function waits on giver_sect_.
74     CriticalSectionScoped cs(giver_sect_);
75     return pass_count_;
76   }
77
78  private:
79   // Wait/Signal forms a classical semaphore on |being_passed_|.
80   // These functions must be called with crit_sect_ held.
81   bool WaitUntilBatonOffered(int timeout_ms) {
82     while (!being_passed_) {
83       if (!cond_var_->SleepCS(*crit_sect_, timeout_ms)) {
84         return false;
85       }
86     }
87     being_passed_ = false;
88     cond_var_->Wake();
89     return true;
90   }
91
92   void SignalBatonAvailable() {
93     assert(!being_passed_);
94     being_passed_ = true;
95     cond_var_->Wake();
96   }
97
98   // Timeout extension: Wait for a limited time for someone else to
99   // take it, and take it if it's not taken.
100   // Returns true if resource is taken by someone else, false
101   // if it is taken back by the caller.
102   // This function must be called with both |giver_sect_| and
103   // |crit_sect_| held.
104   bool TakeBatonIfStillFree(int timeout_ms) {
105     bool not_timeout = true;
106     while (being_passed_ && not_timeout) {
107       not_timeout = cond_var_->SleepCS(*crit_sect_, timeout_ms);
108       // If we're woken up while variable is still held, we may have
109       // gotten a wakeup destined for a grabber thread.
110       // This situation is not treated specially here.
111     }
112     if (!being_passed_) {
113       return true;
114     } else {
115       assert(!not_timeout);
116       being_passed_ = false;
117       return false;
118     }
119   }
120
121   // Lock that ensures that there is only one thread in the active
122   // part of Pass() at a time.
123   // |giver_sect_| must always be acquired before |cond_var_|.
124   CriticalSectionWrapper* giver_sect_;
125   // Lock that protects |being_passed_|.
126   CriticalSectionWrapper* crit_sect_;
127   ConditionVariableWrapper* cond_var_;
128   bool being_passed_;
129   // Statistics information: Number of successfull passes.
130   int pass_count_;
131 };
132
133 // Function that waits on a Baton, and passes it right back.
134 // We expect these calls never to time out.
135 bool WaitingRunFunction(void* obj) {
136   Baton* the_baton = static_cast<Baton*> (obj);
137   EXPECT_TRUE(the_baton->Grab(kLongWaitMs));
138   EXPECT_TRUE(the_baton->Pass(kLongWaitMs));
139   return true;
140 }
141
142 class CondVarTest : public ::testing::Test {
143  public:
144   CondVarTest() {}
145
146   virtual void SetUp() {
147     thread_ = ThreadWrapper::CreateThread(&WaitingRunFunction,
148                                           &baton_);
149     unsigned int id = 42;
150     ASSERT_TRUE(thread_->Start(id));
151   }
152
153   virtual void TearDown() {
154     // We have to wake the thread in order to make it obey the stop order.
155     // But we don't know if the thread has completed the run function, so
156     // we don't know if it will exit before or after the Pass.
157     // Thus, we need to pin it down inside its Run function (between Grab
158     // and Pass).
159     ASSERT_TRUE(baton_.Pass(kShortWaitMs));
160     thread_->SetNotAlive();
161     ASSERT_TRUE(baton_.Grab(kShortWaitMs));
162     ASSERT_TRUE(thread_->Stop());
163     delete thread_;
164   }
165
166  protected:
167   Baton baton_;
168
169  private:
170   ThreadWrapper* thread_;
171 };
172
173 // The SetUp and TearDown functions use condition variables.
174 // This test verifies those pieces in isolation.
175 TEST_F(CondVarTest, InitFunctionsWork) {
176   // All relevant asserts are in the SetUp and TearDown functions.
177 }
178
179 // This test verifies that one can use the baton multiple times.
180 TEST_F(CondVarTest, PassBatonMultipleTimes) {
181   const int kNumberOfRounds = 2;
182   for (int i = 0; i < kNumberOfRounds; ++i) {
183     ASSERT_TRUE(baton_.Pass(kShortWaitMs));
184     ASSERT_TRUE(baton_.Grab(kShortWaitMs));
185   }
186   EXPECT_EQ(2 * kNumberOfRounds, baton_.PassCount());
187 }
188
189 }  // anonymous namespace
190
191 }  // namespace webrtc