mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 22:00:47 +01:00

In https://webrtc-review.googlesource.com/c/src/+/1560 we moved WebRTC from src/webrtc to src/ (in order to preserve an healthy git history). This CL takes care of fixing header guards, #include paths, etc... NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true TBR=tommi@webrtc.org Bug: chromium:611808 Change-Id: Iea91618212bee0af16aa3f05071eab8f93706578 Reviewed-on: https://webrtc-review.googlesource.com/1561 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Henrik Kjellander <kjellander@webrtc.org> Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/master@{#19846}
198 lines
5.6 KiB
C++
198 lines
5.6 KiB
C++
/*
|
|
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "system_wrappers/source/event_timer_posix.h"
|
|
|
|
#include "rtc_base/criticalsection.h"
|
|
#include "rtc_base/event.h"
|
|
#include "test/gtest.h"
|
|
|
|
namespace webrtc {
|
|
|
|
enum class ThreadState {
|
|
kNotStarted,
|
|
kWaiting,
|
|
kRequestProcessCall,
|
|
kCallingProcess,
|
|
kProcessDone,
|
|
kContinue,
|
|
kExiting,
|
|
kDead
|
|
};
|
|
|
|
class EventTimerPosixTest : public testing::Test, public EventTimerPosix {
|
|
public:
|
|
EventTimerPosixTest()
|
|
: thread_state_(ThreadState::kNotStarted),
|
|
process_event_(false, true),
|
|
main_event_(false, true),
|
|
process_thread_id_(0),
|
|
process_thread_(nullptr) {}
|
|
virtual ~EventTimerPosixTest() {}
|
|
|
|
rtc::PlatformThread* CreateThread() override {
|
|
EXPECT_TRUE(process_thread_ == nullptr);
|
|
process_thread_ =
|
|
new rtc::PlatformThread(Run, this, "EventTimerPosixTestThread");
|
|
return process_thread_;
|
|
}
|
|
|
|
static bool Run(void* obj) {
|
|
return static_cast<EventTimerPosixTest*>(obj)->Process();
|
|
}
|
|
|
|
bool Process() {
|
|
bool res = ProcessInternal();
|
|
if (!res) {
|
|
rtc::CritScope cs(&lock_);
|
|
thread_state_ = ThreadState::kDead;
|
|
main_event_.Set();
|
|
}
|
|
return res;
|
|
}
|
|
|
|
bool ProcessInternal() {
|
|
{
|
|
rtc::CritScope cs(&lock_);
|
|
if (thread_state_ == ThreadState::kNotStarted) {
|
|
if (!ChangeThreadState(ThreadState::kNotStarted,
|
|
ThreadState::kContinue)) {
|
|
ADD_FAILURE() << "Unable to start process thread";
|
|
return false;
|
|
}
|
|
process_thread_id_ = rtc::CurrentThreadId();
|
|
}
|
|
}
|
|
|
|
if (!ChangeThreadState(ThreadState::kContinue, ThreadState::kWaiting))
|
|
return false;
|
|
|
|
if (!AwaitThreadState(ThreadState::kRequestProcessCall,
|
|
rtc::Event::kForever))
|
|
return false;
|
|
|
|
if (!ChangeThreadState(ThreadState::kRequestProcessCall,
|
|
ThreadState::kCallingProcess))
|
|
return false;
|
|
|
|
EventTimerPosix::Process();
|
|
|
|
if (!ChangeThreadState(ThreadState::kCallingProcess,
|
|
ThreadState::kProcessDone))
|
|
return false;
|
|
|
|
if (!AwaitThreadState(ThreadState::kContinue, rtc::Event::kForever))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IsProcessThread() {
|
|
rtc::CritScope cs(&lock_);
|
|
return process_thread_id_ == rtc::CurrentThreadId();
|
|
}
|
|
|
|
bool ChangeThreadState(ThreadState prev_state, ThreadState new_state) {
|
|
rtc::CritScope cs(&lock_);
|
|
if (thread_state_ != prev_state)
|
|
return false;
|
|
thread_state_ = new_state;
|
|
if (IsProcessThread()) {
|
|
main_event_.Set();
|
|
} else {
|
|
process_event_.Set();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool AwaitThreadState(ThreadState state, int timeout) {
|
|
rtc::Event* event = IsProcessThread() ? &process_event_ : &main_event_;
|
|
do {
|
|
rtc::CritScope cs(&lock_);
|
|
if (state != ThreadState::kDead && thread_state_ == ThreadState::kExiting)
|
|
return false;
|
|
if (thread_state_ == state)
|
|
return true;
|
|
} while (event->Wait(timeout));
|
|
return false;
|
|
}
|
|
|
|
bool CallProcess(int timeout_ms) {
|
|
return AwaitThreadState(ThreadState::kWaiting, timeout_ms) &&
|
|
ChangeThreadState(ThreadState::kWaiting,
|
|
ThreadState::kRequestProcessCall);
|
|
}
|
|
|
|
bool AwaitProcessDone(int timeout_ms) {
|
|
return AwaitThreadState(ThreadState::kProcessDone, timeout_ms) &&
|
|
ChangeThreadState(ThreadState::kProcessDone, ThreadState::kContinue);
|
|
}
|
|
|
|
void TearDown() override {
|
|
if (process_thread_) {
|
|
{
|
|
rtc::CritScope cs(&lock_);
|
|
if (thread_state_ != ThreadState::kDead) {
|
|
thread_state_ = ThreadState::kExiting;
|
|
process_event_.Set();
|
|
}
|
|
}
|
|
ASSERT_TRUE(AwaitThreadState(ThreadState::kDead, 5000));
|
|
}
|
|
}
|
|
|
|
ThreadState thread_state_;
|
|
rtc::CriticalSection lock_;
|
|
rtc::Event process_event_;
|
|
rtc::Event main_event_;
|
|
rtc::PlatformThreadId process_thread_id_;
|
|
rtc::PlatformThread* process_thread_;
|
|
};
|
|
|
|
TEST_F(EventTimerPosixTest, WaiterBlocksUntilTimeout) {
|
|
const int kTimerIntervalMs = 100;
|
|
const int kTimeoutMs = 5000;
|
|
ASSERT_TRUE(StartTimer(false, kTimerIntervalMs));
|
|
ASSERT_TRUE(CallProcess(kTimeoutMs));
|
|
EventTypeWrapper res = Wait(kTimeoutMs);
|
|
EXPECT_EQ(kEventSignaled, res);
|
|
ASSERT_TRUE(AwaitProcessDone(kTimeoutMs));
|
|
}
|
|
|
|
TEST_F(EventTimerPosixTest, WaiterWakesImmediatelyAfterTimeout) {
|
|
const int kTimerIntervalMs = 100;
|
|
const int kTimeoutMs = 5000;
|
|
ASSERT_TRUE(StartTimer(false, kTimerIntervalMs));
|
|
ASSERT_TRUE(CallProcess(kTimeoutMs));
|
|
ASSERT_TRUE(AwaitProcessDone(kTimeoutMs));
|
|
EventTypeWrapper res = Wait(0);
|
|
EXPECT_EQ(kEventSignaled, res);
|
|
}
|
|
|
|
TEST_F(EventTimerPosixTest, WaiterBlocksUntilTimeoutProcessInactiveOnStart) {
|
|
const int kTimerIntervalMs = 100;
|
|
const int kTimeoutMs = 5000;
|
|
// First call to StartTimer initializes thread.
|
|
ASSERT_TRUE(StartTimer(false, kTimerIntervalMs));
|
|
|
|
// Process thread currently _not_ blocking on Process() call.
|
|
ASSERT_TRUE(AwaitThreadState(ThreadState::kWaiting, kTimeoutMs));
|
|
|
|
// Start new one-off timer, then call Process().
|
|
ASSERT_TRUE(StartTimer(false, kTimerIntervalMs));
|
|
ASSERT_TRUE(CallProcess(kTimeoutMs));
|
|
|
|
EventTypeWrapper res = Wait(kTimeoutMs);
|
|
EXPECT_EQ(kEventSignaled, res);
|
|
|
|
ASSERT_TRUE(AwaitProcessDone(kTimeoutMs));
|
|
}
|
|
|
|
} // namespace webrtc
|