Delete class EventTimerWrapper.

Only user, iSACTest, refactored to use a sleep instead.

Bug: webrtc:3380
Change-Id: I683a5a05349f75a17e5d2a02d4a20a9cf059a28f
Reviewed-on: https://webrtc-review.googlesource.com/96802
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24541}
This commit is contained in:
Niels Möller 2018-09-03 11:04:03 +02:00 committed by Commit Bot
parent 3613fef7a2
commit a421775a6d
9 changed files with 8 additions and 690 deletions

View file

@ -26,7 +26,7 @@
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "modules/audio_coding/codecs/audio_format_conversion.h"
#include "modules/audio_coding/test/utility.h"
#include "system_wrappers/include/event_wrapper.h"
#include "system_wrappers/include/sleep.h"
#include "test/testsupport/fileutils.h"
namespace webrtc {
@ -251,15 +251,19 @@ void ISACTest::EncodeDecode(int testNr,
_channel_B2A->ResetStats();
char currentTime[500];
EventTimerWrapper* myEvent = EventTimerWrapper::Create();
EXPECT_TRUE(myEvent->StartTimer(true, 10));
int64_t time_ms = rtc::TimeMillis();
while (!(_inFileA.EndOfFile() || _inFileA.Rewinded())) {
Run10ms();
_myTimer.Tick10ms();
_myTimer.CurrentTimeHMS(currentTime);
if ((adaptiveMode) && (_testMode != 0)) {
myEvent->Wait(5000);
time_ms += 10;
int64_t time_left_ms = time_ms - rtc::TimeMillis();
if (time_left_ms > 0) {
SleepMs(time_left_ms);
}
EXPECT_TRUE(_acmA->SendCodec());
EXPECT_TRUE(_acmB->SendCodec());
}

View file

@ -25,8 +25,6 @@ rtc_static_library("system_wrappers") {
"source/cpu_features.cc",
"source/cpu_info.cc",
"source/event.cc",
"source/event_timer_win.cc",
"source/event_timer_win.h",
"source/rtp_to_ntp_estimator.cc",
"source/sleep.cc",
]
@ -46,13 +44,6 @@ rtc_static_library("system_wrappers") {
"//third_party/abseil-cpp/absl/types:optional",
]
if (is_posix || is_fuchsia) {
sources += [
"source/event_timer_posix.cc",
"source/event_timer_posix.h",
]
}
if (is_android) {
defines += [ "WEBRTC_THREAD_RR" ]
@ -209,10 +200,6 @@ if (rtc_include_tests) {
"source/rtp_to_ntp_estimator_unittest.cc",
]
if (is_posix || is_fuchsia) {
sources += [ "source/event_timer_posix_unittest.cc" ]
}
deps = [
":metrics_api",
":metrics_default",

View file

@ -20,8 +20,6 @@ enum EventTypeWrapper {
#define WEBRTC_EVENT_INFINITE 0xffffffff
class EventTimerWrapper;
class EventWrapper {
public:
// Factory method. Constructor disabled.
@ -50,20 +48,6 @@ class EventWrapper {
virtual EventTypeWrapper Wait(unsigned long max_time) = 0;
};
class EventTimerWrapper : public EventWrapper {
public:
static EventTimerWrapper* Create();
// Starts a timer that will call a non-sticky version of Set() either once
// or periodically. If the timer is periodic it ensures that there is no
// drift over time relative to the system clock.
//
// |time| is in milliseconds.
virtual bool StartTimer(bool periodic, unsigned long time) = 0;
virtual bool StopTimer() = 0;
};
} // namespace webrtc
#endif // SYSTEM_WRAPPERS_INCLUDE_EVENT_WRAPPER_H_

View file

@ -12,14 +12,11 @@
#if defined(_WIN32)
#include <windows.h>
#include "system_wrappers/source/event_timer_win.h"
#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
#include <ApplicationServices/ApplicationServices.h>
#include <pthread.h>
#include "system_wrappers/source/event_timer_posix.h"
#else
#include <pthread.h>
#include "system_wrappers/source/event_timer_posix.h"
#endif
#include "rtc_base/event.h"

View file

@ -1,275 +0,0 @@
/*
* Copyright (c) 2011 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"
#if defined(WEBRTC_ANDROID)
#include <android/api-level.h>
#endif
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include "rtc_base/checks.h"
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
// Chromium build is always defining this macro if __ANDROID_API__ < 20.
#undef HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC
#endif
#if defined(WEBRTC_ANDROID) && defined(__ANDROID_API__)
#define HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC (__ANDROID_API__ < 21)
#else
#define HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC 0
#endif
namespace webrtc {
// static
EventTimerWrapper* EventTimerWrapper::Create() {
return new EventTimerPosix();
}
const int64_t kNanosecondsPerMillisecond = 1000000;
const int64_t kNanosecondsPerSecond = 1000000000;
EventTimerPosix::EventTimerPosix()
: event_set_(false),
timer_thread_(nullptr),
created_at_(),
periodic_(false),
time_ms_(0),
count_(0),
is_stopping_(false) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex_, &attr);
pthread_condattr_t cond_attr;
pthread_condattr_init(&cond_attr);
// TODO(sprang): Remove HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC special case once
// all supported Android platforms support pthread_condattr_setclock.
// TODO(sprang): Add support for monotonic clock on Apple platforms.
#if !(defined(WEBRTC_MAC) || defined(WEBRTC_IOS)) && \
!(defined(WEBRTC_ANDROID) && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
#endif
pthread_cond_init(&cond_, &cond_attr);
pthread_condattr_destroy(&cond_attr);
}
EventTimerPosix::~EventTimerPosix() {
StopTimer();
pthread_cond_destroy(&cond_);
pthread_mutex_destroy(&mutex_);
}
// TODO(pbos): Make this void.
bool EventTimerPosix::Set() {
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
event_set_ = true;
pthread_cond_signal(&cond_);
pthread_mutex_unlock(&mutex_);
return true;
}
EventTypeWrapper EventTimerPosix::Wait(unsigned long timeout_ms) {
int ret_val = 0;
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
if (!event_set_) {
if (WEBRTC_EVENT_INFINITE != timeout_ms) {
timespec end_at;
#ifndef WEBRTC_MAC
clock_gettime(CLOCK_MONOTONIC, &end_at);
#else
timeval value;
struct timezone time_zone;
time_zone.tz_minuteswest = 0;
time_zone.tz_dsttime = 0;
gettimeofday(&value, &time_zone);
TIMEVAL_TO_TIMESPEC(&value, &end_at);
#endif
end_at.tv_sec += timeout_ms / 1000;
end_at.tv_nsec += (timeout_ms % 1000) * kNanosecondsPerMillisecond;
if (end_at.tv_nsec >= kNanosecondsPerSecond) {
end_at.tv_sec++;
end_at.tv_nsec -= kNanosecondsPerSecond;
}
while (ret_val == 0 && !event_set_) {
#if defined(WEBRTC_ANDROID) && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC
ret_val = pthread_cond_timedwait_monotonic_np(&cond_, &mutex_, &end_at);
#else
ret_val = pthread_cond_timedwait(&cond_, &mutex_, &end_at);
#endif // WEBRTC_ANDROID && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC
}
} else {
while (ret_val == 0 && !event_set_)
ret_val = pthread_cond_wait(&cond_, &mutex_);
}
}
RTC_DCHECK(ret_val == 0 || ret_val == ETIMEDOUT);
// Reset and signal if set, regardless of why the thread woke up.
if (event_set_) {
ret_val = 0;
event_set_ = false;
}
pthread_mutex_unlock(&mutex_);
return ret_val == 0 ? kEventSignaled : kEventTimeout;
}
EventTypeWrapper EventTimerPosix::Wait(timespec* end_at, bool reset_event) {
int ret_val = 0;
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
if (reset_event) {
// Only wake for new events or timeouts.
event_set_ = false;
}
while (ret_val == 0 && !event_set_) {
#if defined(WEBRTC_ANDROID) && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC
ret_val = pthread_cond_timedwait_monotonic_np(&cond_, &mutex_, end_at);
#else
ret_val = pthread_cond_timedwait(&cond_, &mutex_, end_at);
#endif // WEBRTC_ANDROID && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC
}
RTC_DCHECK(ret_val == 0 || ret_val == ETIMEDOUT);
// Reset and signal if set, regardless of why the thread woke up.
if (event_set_) {
ret_val = 0;
event_set_ = false;
}
pthread_mutex_unlock(&mutex_);
return ret_val == 0 ? kEventSignaled : kEventTimeout;
}
rtc::PlatformThread* EventTimerPosix::CreateThread() {
const char* kThreadName = "WebRtc_event_timer_thread";
return new rtc::PlatformThread(Run, this, kThreadName);
}
bool EventTimerPosix::StartTimer(bool periodic, unsigned long time_ms) {
pthread_mutex_lock(&mutex_);
if (timer_thread_) {
if (periodic_) {
// Timer already started.
pthread_mutex_unlock(&mutex_);
return false;
} else {
// New one shot timer.
time_ms_ = time_ms;
created_at_.tv_sec = 0;
timer_event_->Set();
pthread_mutex_unlock(&mutex_);
return true;
}
}
// Start the timer thread.
timer_event_.reset(new EventTimerPosix());
timer_thread_.reset(CreateThread());
periodic_ = periodic;
time_ms_ = time_ms;
timer_thread_->Start();
timer_thread_->SetPriority(rtc::kRealtimePriority);
pthread_mutex_unlock(&mutex_);
return true;
}
bool EventTimerPosix::Run(void* obj) {
return static_cast<EventTimerPosix*>(obj)->Process();
}
bool EventTimerPosix::Process() {
pthread_mutex_lock(&mutex_);
if (is_stopping_) {
pthread_mutex_unlock(&mutex_);
return false;
}
if (created_at_.tv_sec == 0) {
#ifndef WEBRTC_MAC
RTC_CHECK_EQ(0, clock_gettime(CLOCK_MONOTONIC, &created_at_));
#else
timeval value;
struct timezone time_zone;
time_zone.tz_minuteswest = 0;
time_zone.tz_dsttime = 0;
gettimeofday(&value, &time_zone);
TIMEVAL_TO_TIMESPEC(&value, &created_at_);
#endif
count_ = 0;
}
timespec end_at;
unsigned long long total_delta_ms = time_ms_ * ++count_;
if (!periodic_ && count_ >= 1) {
// No need to wake up often if we're not going to signal waiting threads.
total_delta_ms =
std::min<uint64_t>(total_delta_ms, 60 * kNanosecondsPerSecond);
}
end_at.tv_sec = created_at_.tv_sec + total_delta_ms / 1000;
end_at.tv_nsec = created_at_.tv_nsec +
(total_delta_ms % 1000) * kNanosecondsPerMillisecond;
if (end_at.tv_nsec >= kNanosecondsPerSecond) {
end_at.tv_sec++;
end_at.tv_nsec -= kNanosecondsPerSecond;
}
pthread_mutex_unlock(&mutex_);
// Reset event on first call so that we don't immediately return here if this
// thread was not blocked on timer_event_->Wait when the StartTimer() call
// was made.
if (timer_event_->Wait(&end_at, count_ == 1) == kEventSignaled)
return true;
pthread_mutex_lock(&mutex_);
if (periodic_ || count_ == 1)
Set();
pthread_mutex_unlock(&mutex_);
return true;
}
bool EventTimerPosix::StopTimer() {
pthread_mutex_lock(&mutex_);
is_stopping_ = true;
pthread_mutex_unlock(&mutex_);
if (timer_event_)
timer_event_->Set();
if (timer_thread_) {
timer_thread_->Stop();
timer_thread_.reset();
}
timer_event_.reset();
// Set time to zero to force new reference time for the timer.
memset(&created_at_, 0, sizeof(created_at_));
count_ = 0;
return true;
}
} // namespace webrtc

View file

@ -1,64 +0,0 @@
/*
* Copyright (c) 2011 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.
*/
#ifndef SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
#define SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
#include "system_wrappers/include/event_wrapper.h"
#include <memory>
#include <pthread.h>
#include <time.h>
#include "rtc_base/platform_thread.h"
namespace webrtc {
enum State { kUp = 1, kDown = 2 };
class EventTimerPosix : public EventTimerWrapper {
public:
EventTimerPosix();
~EventTimerPosix() override;
EventTypeWrapper Wait(unsigned long max_time) override;
bool Set() override;
bool StartTimer(bool periodic, unsigned long time) override;
bool StopTimer() override;
private:
friend class EventTimerPosixTest;
static bool Run(void* obj);
bool Process();
EventTypeWrapper Wait(timespec* end_at, bool reset_state);
virtual rtc::PlatformThread* CreateThread();
pthread_cond_t cond_;
pthread_mutex_t mutex_;
bool event_set_;
// TODO(pbos): Remove unique_ptr and use PlatformThread directly.
std::unique_ptr<rtc::PlatformThread> timer_thread_;
std::unique_ptr<EventTimerPosix> timer_event_;
timespec created_at_;
bool periodic_;
unsigned long time_ms_;
unsigned long count_;
bool is_stopping_;
};
} // namespace webrtc
#endif // SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_

View file

@ -1,198 +0,0 @@
/*
* 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) {}
~EventTimerPosixTest() override {}
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

View file

@ -1,77 +0,0 @@
/*
* Copyright (c) 2012 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_win.h"
#include "mmsystem.h"
namespace webrtc {
// static
EventTimerWrapper* EventTimerWrapper::Create() {
return new EventTimerWin();
}
EventTimerWin::EventTimerWin()
: event_(::CreateEvent(NULL, // security attributes
FALSE, // manual reset
FALSE, // initial state
NULL)), // name of event
timerID_(NULL) {}
EventTimerWin::~EventTimerWin() {
StopTimer();
CloseHandle(event_);
}
bool EventTimerWin::Set() {
// Note: setting an event that is already set has no effect.
return SetEvent(event_) == 1;
}
EventTypeWrapper EventTimerWin::Wait(unsigned long max_time) {
unsigned long res = WaitForSingleObject(event_, max_time);
switch (res) {
case WAIT_OBJECT_0:
return kEventSignaled;
case WAIT_TIMEOUT:
return kEventTimeout;
default:
return kEventError;
}
}
bool EventTimerWin::StartTimer(bool periodic, unsigned long time) {
if (timerID_ != NULL) {
timeKillEvent(timerID_);
timerID_ = NULL;
}
if (periodic) {
timerID_ = timeSetEvent(time, 0, (LPTIMECALLBACK)HANDLE(event_), 0,
TIME_PERIODIC | TIME_CALLBACK_EVENT_PULSE);
} else {
timerID_ = timeSetEvent(time, 0, (LPTIMECALLBACK)HANDLE(event_), 0,
TIME_ONESHOT | TIME_CALLBACK_EVENT_SET);
}
return timerID_ != NULL;
}
bool EventTimerWin::StopTimer() {
if (timerID_ != NULL) {
timeKillEvent(timerID_);
timerID_ = NULL;
}
return true;
}
} // namespace webrtc

View file

@ -1,40 +0,0 @@
/*
* Copyright (c) 2011 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.
*/
#ifndef SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
#define SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
#include <stdint.h>
#include <windows.h>
#include "system_wrappers/include/event_wrapper.h"
namespace webrtc {
class EventTimerWin : public EventTimerWrapper {
public:
EventTimerWin();
~EventTimerWin() override;
EventTypeWrapper Wait(unsigned long max_time) override;
bool Set() override;
bool StartTimer(bool periodic, unsigned long time) override;
bool StopTimer() override;
private:
HANDLE event_;
uint32_t timerID_;
};
} // namespace webrtc
#endif // SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_