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