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