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

Side by Side Diff: webrtc/system_wrappers/source/condition_variable_unittest.cc

Issue 2790533002: Remove ALL usage of CriticalSectionWrapper. (Closed)
Patch Set: remove winXP rw_lock include Created 3 years, 8 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
OLDNEW
(Empty)
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 // TODO(tommi): Remove completely. As is there is still some code for Windows
12 // that relies on ConditionVariableEventWin, but code has been removed on other
13 // platforms.
14 #if defined(WEBRTC_WIN)
15
16 #include "webrtc/base/platform_thread.h"
17 #include "webrtc/base/timeutils.h"
18 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
19 #include "webrtc/system_wrappers/source/condition_variable_event_win.h"
20 #include "webrtc/test/gtest.h"
21
22 namespace webrtc {
23
24 namespace {
25
26 const int kLongWaitMs = 100 * 1000; // A long time in testing terms
27 const int kShortWaitMs = 2 * 1000; // Long enough for process switches to happen
28 const int kVeryShortWaitMs = 20; // Used when we want a timeout
29
30 // A Baton is one possible control structure one can build using
31 // conditional variables.
32 // A Baton is always held by one and only one active thread - unlike
33 // a lock, it can never be free.
34 // One can pass it or grab it - both calls have timeouts.
35 // Note - a production tool would guard against passing it without
36 // grabbing it first. This one is for testing, so it doesn't.
37 class Baton {
38 public:
39 Baton()
40 : being_passed_(false),
41 pass_count_(0) {
42 InitializeCriticalSection(&crit_sect_);
43 }
44
45 ~Baton() {
46 DeleteCriticalSection(&crit_sect_);
47 }
48
49 // Pass the baton. Returns false if baton is not picked up in |max_msecs|.
50 // Only one process can pass at the same time; this property is
51 // ensured by the |giver_sect_| lock.
52 bool Pass(uint32_t max_msecs) {
53 CriticalSectionScoped cs_giver(&giver_sect_);
54 EnterCriticalSection(&crit_sect_);
55 SignalBatonAvailable();
56 const bool result = TakeBatonIfStillFree(max_msecs);
57 if (result) {
58 ++pass_count_;
59 }
60 LeaveCriticalSection(&crit_sect_);
61 return result;
62 }
63
64 // Grab the baton. Returns false if baton is not passed.
65 bool Grab(uint32_t max_msecs) {
66 EnterCriticalSection(&crit_sect_);
67 bool ret = WaitUntilBatonOffered(max_msecs);
68 LeaveCriticalSection(&crit_sect_);
69 return ret;
70 }
71
72 int PassCount() {
73 // We don't allow polling PassCount() during a Pass()-call since there is
74 // no guarantee that |pass_count_| is incremented until the Pass()-call
75 // finishes. I.e. the Grab()-call may finish before |pass_count_| has been
76 // incremented.
77 // Thus, this function waits on giver_sect_.
78 CriticalSectionScoped cs(&giver_sect_);
79 return pass_count_;
80 }
81
82 private:
83 // Wait/Signal forms a classical semaphore on |being_passed_|.
84 // These functions must be called with crit_sect_ held.
85 bool WaitUntilBatonOffered(int timeout_ms) {
86 while (!being_passed_) {
87 if (!cond_var_.SleepCS(&crit_sect_, timeout_ms)) {
88 return false;
89 }
90 }
91 being_passed_ = false;
92 cond_var_.Wake();
93 return true;
94 }
95
96 void SignalBatonAvailable() {
97 assert(!being_passed_);
98 being_passed_ = true;
99 cond_var_.Wake();
100 }
101
102 // Timeout extension: Wait for a limited time for someone else to
103 // take it, and take it if it's not taken.
104 // Returns true if resource is taken by someone else, false
105 // if it is taken back by the caller.
106 // This function must be called with both |giver_sect_| and
107 // |crit_sect_| held.
108 bool TakeBatonIfStillFree(int timeout_ms) {
109 bool not_timeout = true;
110 while (being_passed_ && not_timeout) {
111 not_timeout = cond_var_.SleepCS(&crit_sect_, timeout_ms);
112 // If we're woken up while variable is still held, we may have
113 // gotten a wakeup destined for a grabber thread.
114 // This situation is not treated specially here.
115 }
116 if (!being_passed_)
117 return true;
118 assert(!not_timeout);
119 being_passed_ = false;
120 return false;
121 }
122
123 // Lock that ensures that there is only one thread in the active
124 // part of Pass() at a time.
125 // |giver_sect_| must always be acquired before |cond_var_|.
126 CriticalSectionWrapper giver_sect_;
127 // Lock that protects |being_passed_|.
128 CRITICAL_SECTION crit_sect_;
129 ConditionVariableEventWin cond_var_;
130 bool being_passed_;
131 // Statistics information: Number of successfull passes.
132 int pass_count_;
133 };
134
135 // Function that waits on a Baton, and passes it right back.
136 // We expect these calls never to time out.
137 bool WaitingRunFunction(void* obj) {
138 Baton* the_baton = static_cast<Baton*> (obj);
139 EXPECT_TRUE(the_baton->Grab(kLongWaitMs));
140 EXPECT_TRUE(the_baton->Pass(kLongWaitMs));
141 return true;
142 }
143
144 class CondVarTest : public ::testing::Test {
145 public:
146 CondVarTest() : thread_(&WaitingRunFunction, &baton_, "CondVarTest") {}
147
148 virtual void SetUp() {
149 thread_.Start();
150 }
151
152 virtual void TearDown() {
153 // We have to wake the thread in order to make it obey the stop order.
154 // But we don't know if the thread has completed the run function, so
155 // we don't know if it will exit before or after the Pass.
156 // Thus, we need to pin it down inside its Run function (between Grab
157 // and Pass).
158 ASSERT_TRUE(baton_.Pass(kShortWaitMs));
159 ASSERT_TRUE(baton_.Grab(kShortWaitMs));
160 thread_.Stop();
161 }
162
163 protected:
164 Baton baton_;
165
166 private:
167 rtc::PlatformThread thread_;
168 };
169
170 // The SetUp and TearDown functions use condition variables.
171 // This test verifies those pieces in isolation.
172 // Disabled due to flakiness. See bug 4262 for details.
173 TEST_F(CondVarTest, DISABLED_InitFunctionsWork) {
174 // All relevant asserts are in the SetUp and TearDown functions.
175 }
176
177 // This test verifies that one can use the baton multiple times.
178 TEST_F(CondVarTest, DISABLED_PassBatonMultipleTimes) {
179 const int kNumberOfRounds = 2;
180 for (int i = 0; i < kNumberOfRounds; ++i) {
181 ASSERT_TRUE(baton_.Pass(kShortWaitMs));
182 ASSERT_TRUE(baton_.Grab(kShortWaitMs));
183 }
184 EXPECT_EQ(2 * kNumberOfRounds, baton_.PassCount());
185 }
186
187 TEST(CondVarWaitTest, WaitingWaits) {
188 CRITICAL_SECTION crit_sect;
189 InitializeCriticalSection(&crit_sect);
190 ConditionVariableEventWin cond_var;
191 EnterCriticalSection(&crit_sect);
192 int64_t start_ms = rtc::TimeMillis();
193 EXPECT_FALSE(cond_var.SleepCS(&crit_sect, kVeryShortWaitMs));
194 int64_t end_ms = rtc::TimeMillis();
195 EXPECT_LE(start_ms + kVeryShortWaitMs, end_ms)
196 << "actual elapsed:" << end_ms - start_ms;
197 LeaveCriticalSection(&crit_sect);
198 DeleteCriticalSection(&crit_sect);
199 }
200
201 } // anonymous namespace
202
203 } // namespace webrtc
204
205 #endif // defined(WEBRTC_WIN)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698