Reformatted condition_variable* in system_wrappers.
BUG= TEST=Ran trybots. Review URL: https://webrtc-codereview.appspot.com/937017 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3095 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
12b828ac90
commit
a36d75a03c
@ -12,30 +12,31 @@
|
|||||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class CriticalSectionWrapper;
|
class CriticalSectionWrapper;
|
||||||
|
|
||||||
class ConditionVariableWrapper
|
class ConditionVariableWrapper {
|
||||||
{
|
public:
|
||||||
public:
|
// Factory method, constructor disabled.
|
||||||
// Factory method, constructor disabled.
|
static ConditionVariableWrapper* CreateConditionVariable();
|
||||||
static ConditionVariableWrapper* CreateConditionVariable();
|
|
||||||
|
|
||||||
virtual ~ConditionVariableWrapper() {}
|
virtual ~ConditionVariableWrapper() {}
|
||||||
|
|
||||||
// Calling thread will atomically release critSect and wait until next
|
// Calling thread will atomically release crit_sect and wait until next
|
||||||
// some other thread calls Wake() or WakeAll().
|
// some other thread calls Wake() or WakeAll().
|
||||||
virtual void SleepCS(CriticalSectionWrapper& critSect) = 0;
|
virtual void SleepCS(CriticalSectionWrapper& crit_sect) = 0;
|
||||||
|
|
||||||
// Same as above but with a timeout.
|
// Same as above but with a timeout.
|
||||||
virtual bool SleepCS(CriticalSectionWrapper& critSect,
|
virtual bool SleepCS(CriticalSectionWrapper& crit_sect,
|
||||||
unsigned long maxTimeInMS) = 0;
|
unsigned long max_time_in_ms) = 0;
|
||||||
|
|
||||||
// Wakes one thread calling SleepCS().
|
// Wakes one thread calling SleepCS().
|
||||||
virtual void Wake() = 0;
|
virtual void Wake() = 0;
|
||||||
|
|
||||||
// Wakes all threads calling SleepCS().
|
// Wakes all threads calling SleepCS().
|
||||||
virtual void WakeAll() = 0;
|
virtual void WakeAll() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
||||||
|
@ -9,29 +9,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "condition_variable_wrapper.h"
|
#include "condition_variable_win.h"
|
||||||
#include "condition_variable_win.h"
|
#include "condition_variable_wrapper.h"
|
||||||
#elif defined(WEBRTC_LINUX)
|
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "condition_variable_wrapper.h"
|
#include "condition_variable_posix.h"
|
||||||
#include "condition_variable_posix.h"
|
#include "condition_variable_wrapper.h"
|
||||||
#elif defined(WEBRTC_MAC)
|
|
||||||
#include <pthread.h>
|
|
||||||
#include "condition_variable_wrapper.h"
|
|
||||||
#include "condition_variable_posix.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
ConditionVariableWrapper*
|
|
||||||
ConditionVariableWrapper::CreateConditionVariable()
|
ConditionVariableWrapper* ConditionVariableWrapper::CreateConditionVariable() {
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return new ConditionVariableWindows;
|
return new ConditionVariableWindows;
|
||||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||||
return ConditionVariablePosix::Create();
|
return ConditionVariablePosix::Create();
|
||||||
#else
|
#else
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -10,142 +10,123 @@
|
|||||||
|
|
||||||
#include "condition_variable_posix.h"
|
#include "condition_variable_posix.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#if defined(WEBRTC_LINUX)
|
#if defined(WEBRTC_LINUX)
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#else
|
#else
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "critical_section_posix.h"
|
#include "critical_section_posix.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
ConditionVariableWrapper* ConditionVariablePosix::Create()
|
|
||||||
{
|
|
||||||
ConditionVariablePosix* ptr = new ConditionVariablePosix;
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int error = ptr->Construct();
|
ConditionVariableWrapper* ConditionVariablePosix::Create() {
|
||||||
if (error)
|
ConditionVariablePosix* ptr = new ConditionVariablePosix;
|
||||||
{
|
if (!ptr) {
|
||||||
delete ptr;
|
return NULL;
|
||||||
return NULL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
const int error = ptr->Construct();
|
||||||
|
if (error) {
|
||||||
|
delete ptr;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConditionVariablePosix::ConditionVariablePosix()
|
ConditionVariablePosix::ConditionVariablePosix() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConditionVariablePosix::Construct()
|
int ConditionVariablePosix::Construct() {
|
||||||
{
|
|
||||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||||
pthread_cond_init(&_cond, NULL);
|
pthread_cond_init(&cond_, NULL);
|
||||||
#else
|
#else
|
||||||
int result = 0;
|
int result = 0;
|
||||||
pthread_condattr_t condAttr;
|
pthread_condattr_t cond_attr;
|
||||||
result = pthread_condattr_init(&condAttr);
|
result = pthread_condattr_init(&cond_attr);
|
||||||
if (result != 0)
|
if (result != 0) {
|
||||||
{
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
|
||||||
result = pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
|
if (result != 0) {
|
||||||
if (result != 0)
|
return -1;
|
||||||
{
|
}
|
||||||
return -1;
|
result = pthread_cond_init(&cond_, &cond_attr);
|
||||||
}
|
if (result != 0) {
|
||||||
result = pthread_cond_init(&_cond, &condAttr);
|
return -1;
|
||||||
if (result != 0)
|
}
|
||||||
{
|
result = pthread_condattr_destroy(&cond_attr);
|
||||||
return -1;
|
if (result != 0) {
|
||||||
}
|
return -1;
|
||||||
result = pthread_condattr_destroy(&condAttr);
|
}
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConditionVariablePosix::~ConditionVariablePosix()
|
ConditionVariablePosix::~ConditionVariablePosix() {
|
||||||
{
|
pthread_cond_destroy(&cond_);
|
||||||
pthread_cond_destroy(&_cond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConditionVariablePosix::SleepCS(CriticalSectionWrapper& critSect)
|
void ConditionVariablePosix::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||||
{
|
CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
|
||||||
CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
|
&crit_sect);
|
||||||
&critSect);
|
pthread_cond_wait(&cond_, &cs->_mutex);
|
||||||
pthread_cond_wait(&_cond, &cs->_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConditionVariablePosix::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||||
bool
|
unsigned long max_time_inMS) {
|
||||||
ConditionVariablePosix::SleepCS(
|
const unsigned long INFINITE = 0xFFFFFFFF;
|
||||||
CriticalSectionWrapper& critSect,
|
const int MILLISECONDS_PER_SECOND = 1000;
|
||||||
unsigned long maxTimeInMS)
|
|
||||||
{
|
|
||||||
const unsigned long INFINITE = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
const int MILLISECONDS_PER_SECOND = 1000;
|
|
||||||
#ifndef WEBRTC_LINUX
|
#ifndef WEBRTC_LINUX
|
||||||
const int MICROSECONDS_PER_MILLISECOND = 1000;
|
const int MICROSECONDS_PER_MILLISECOND = 1000;
|
||||||
#endif
|
#endif
|
||||||
const int NANOSECONDS_PER_SECOND = 1000000000;
|
const int NANOSECONDS_PER_SECOND = 1000000000;
|
||||||
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||||
|
|
||||||
CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
|
CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
|
||||||
&critSect);
|
&crit_sect);
|
||||||
|
|
||||||
if (maxTimeInMS != INFINITE)
|
if (max_time_inMS != INFINITE) {
|
||||||
{
|
timespec ts;
|
||||||
timespec ts;
|
|
||||||
#ifndef WEBRTC_MAC
|
#ifndef WEBRTC_MAC
|
||||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
#else
|
#else
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else // WEBRTC_MAC
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
ts.tv_sec = tv.tv_sec;
|
ts.tv_sec = tv.tv_sec;
|
||||||
ts.tv_nsec = tv.tv_usec * MICROSECONDS_PER_MILLISECOND;
|
ts.tv_nsec = tv.tv_usec * MICROSECONDS_PER_MILLISECOND;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ts.tv_sec += maxTimeInMS / MILLISECONDS_PER_SECOND;
|
ts.tv_sec += max_time_inMS / MILLISECONDS_PER_SECOND;
|
||||||
ts.tv_nsec += (maxTimeInMS - ((maxTimeInMS / MILLISECONDS_PER_SECOND)*
|
ts.tv_nsec +=
|
||||||
MILLISECONDS_PER_SECOND)) * NANOSECONDS_PER_MILLISECOND;
|
(max_time_inMS
|
||||||
|
- ((max_time_inMS / MILLISECONDS_PER_SECOND) * MILLISECONDS_PER_SECOND))
|
||||||
|
* NANOSECONDS_PER_MILLISECOND;
|
||||||
|
|
||||||
if (ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
if (ts.tv_nsec >= NANOSECONDS_PER_SECOND) {
|
||||||
{
|
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
|
||||||
}
|
|
||||||
const int res = pthread_cond_timedwait(&_cond, &cs->_mutex, &ts);
|
|
||||||
return (res == ETIMEDOUT) ? false : true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pthread_cond_wait(&_cond, &cs->_mutex);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
const int res = pthread_cond_timedwait(&cond_, &cs->_mutex, &ts);
|
||||||
|
return (res == ETIMEDOUT) ? false : true;
|
||||||
|
} else {
|
||||||
|
pthread_cond_wait(&cond_, &cs->_mutex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConditionVariablePosix::Wake()
|
void ConditionVariablePosix::Wake() {
|
||||||
{
|
pthread_cond_signal(&cond_);
|
||||||
pthread_cond_signal(&_cond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConditionVariablePosix::WakeAll()
|
void ConditionVariablePosix::WakeAll() {
|
||||||
{
|
pthread_cond_broadcast(&cond_);
|
||||||
pthread_cond_broadcast(&_cond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -11,29 +11,30 @@
|
|||||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
||||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
||||||
|
|
||||||
#include "condition_variable_wrapper.h"
|
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "condition_variable_wrapper.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
class ConditionVariablePosix : public ConditionVariableWrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static ConditionVariableWrapper* Create();
|
|
||||||
~ConditionVariablePosix();
|
|
||||||
|
|
||||||
void SleepCS(CriticalSectionWrapper& critSect);
|
class ConditionVariablePosix : public ConditionVariableWrapper {
|
||||||
bool SleepCS(CriticalSectionWrapper& critSect, unsigned long maxTimeInMS);
|
public:
|
||||||
void Wake();
|
static ConditionVariableWrapper* Create();
|
||||||
void WakeAll();
|
~ConditionVariablePosix();
|
||||||
|
|
||||||
private:
|
void SleepCS(CriticalSectionWrapper& crit_sect);
|
||||||
ConditionVariablePosix();
|
bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_in_ms);
|
||||||
int Construct();
|
void Wake();
|
||||||
|
void WakeAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pthread_cond_t _cond;
|
ConditionVariablePosix();
|
||||||
|
int Construct();
|
||||||
|
|
||||||
|
private:
|
||||||
|
pthread_cond_t cond_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
||||||
|
@ -21,8 +21,8 @@ namespace webrtc {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const int kLogTrace = false; // Set to true to enable debug logging to stdout.
|
const int kLogTrace = false; // Set to true to enable debug logging to stdout.
|
||||||
const int kLongWaitMs = 100*1000; // A long time in testing terms
|
const int kLongWaitMs = 100 * 1000; // A long time in testing terms
|
||||||
const int kShortWaitMs = 2*1000; // Long enough for process switches to happen
|
const int kShortWaitMs = 2 * 1000; // Long enough for process switches to happen
|
||||||
|
|
||||||
#define LOG(...) WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, __VA_ARGS__);
|
#define LOG(...) WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, __VA_ARGS__);
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ class Baton {
|
|||||||
// Function that waits on a Baton, and passes it right back.
|
// Function that waits on a Baton, and passes it right back.
|
||||||
// We expect these calls never to time out.
|
// We expect these calls never to time out.
|
||||||
bool WaitingRunFunction(void* obj) {
|
bool WaitingRunFunction(void* obj) {
|
||||||
Baton* the_baton = static_cast<Baton*> (obj);
|
Baton* the_baton = static_cast<Baton*>(obj);
|
||||||
LOG("Thread waiting");
|
LOG("Thread waiting");
|
||||||
EXPECT_TRUE(the_baton->Grab(kLongWaitMs));
|
EXPECT_TRUE(the_baton->Grab(kLongWaitMs));
|
||||||
LOG("Thread waking parent");
|
LOG("Thread waking parent");
|
||||||
@ -200,7 +200,7 @@ TEST_F(CondVarTest, PassBatonMultipleTimes) {
|
|||||||
ASSERT_TRUE(baton_.Pass(kShortWaitMs));
|
ASSERT_TRUE(baton_.Pass(kShortWaitMs));
|
||||||
ASSERT_TRUE(baton_.Grab(kShortWaitMs));
|
ASSERT_TRUE(baton_.Grab(kShortWaitMs));
|
||||||
}
|
}
|
||||||
EXPECT_EQ(2*kNumberOfRounds, baton_.PassCount());
|
EXPECT_EQ(2 * kNumberOfRounds, baton_.PassCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
@ -19,18 +19,19 @@
|
|||||||
// implementation into two different files
|
// implementation into two different files
|
||||||
|
|
||||||
#include "condition_variable_win.h"
|
#include "condition_variable_win.h"
|
||||||
|
|
||||||
#include "critical_section_win.h"
|
#include "critical_section_win.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
bool ConditionVariableWindows::_winSupportConditionVariablesPrimitive = false;
|
|
||||||
|
bool ConditionVariableWindows::win_support_condition_variables_primitive_ =
|
||||||
|
false;
|
||||||
static HMODULE library = NULL;
|
static HMODULE library = NULL;
|
||||||
|
|
||||||
PInitializeConditionVariable _PInitializeConditionVariable;
|
PInitializeConditionVariable PInitializeConditionVariable_;
|
||||||
PSleepConditionVariableCS _PSleepConditionVariableCS;
|
PSleepConditionVariableCS PSleepConditionVariableCS_;
|
||||||
PWakeConditionVariable _PWakeConditionVariable;
|
PWakeConditionVariable PWakeConditionVariable_;
|
||||||
PWakeAllConditionVariable _PWakeAllConditionVariable;
|
PWakeAllConditionVariable PWakeAllConditionVariable_;
|
||||||
|
|
||||||
typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
||||||
typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||||
@ -39,186 +40,159 @@ typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
|
|||||||
typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||||
|
|
||||||
ConditionVariableWindows::ConditionVariableWindows()
|
ConditionVariableWindows::ConditionVariableWindows()
|
||||||
: _eventID(WAKEALL_0)
|
: eventID_(WAKEALL_0) {
|
||||||
{
|
if (!library) {
|
||||||
if (!library)
|
// Use native implementation if supported (i.e Vista+)
|
||||||
{
|
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||||
// Use native implementation if supported (i.e Vista+)
|
if (library) {
|
||||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
|
||||||
if (library)
|
|
||||||
{
|
|
||||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
|
||||||
"Loaded Kernel.dll");
|
|
||||||
|
|
||||||
_PInitializeConditionVariable =
|
PInitializeConditionVariable_ =
|
||||||
(PInitializeConditionVariable) GetProcAddress(
|
(PInitializeConditionVariable) GetProcAddress(
|
||||||
library,
|
library, "InitializeConditionVariable");
|
||||||
"InitializeConditionVariable");
|
PSleepConditionVariableCS_ = (PSleepConditionVariableCS) GetProcAddress(
|
||||||
_PSleepConditionVariableCS =
|
library, "SleepConditionVariableCS");
|
||||||
(PSleepConditionVariableCS)GetProcAddress(
|
PWakeConditionVariable_ = (PWakeConditionVariable) GetProcAddress(
|
||||||
library,
|
library, "WakeConditionVariable");
|
||||||
"SleepConditionVariableCS");
|
PWakeAllConditionVariable_ = (PWakeAllConditionVariable) GetProcAddress(
|
||||||
_PWakeConditionVariable =
|
library, "WakeAllConditionVariable");
|
||||||
(PWakeConditionVariable)GetProcAddress(
|
|
||||||
library,
|
|
||||||
"WakeConditionVariable");
|
|
||||||
_PWakeAllConditionVariable =
|
|
||||||
(PWakeAllConditionVariable)GetProcAddress(
|
|
||||||
library,
|
|
||||||
"WakeAllConditionVariable");
|
|
||||||
|
|
||||||
if(_PInitializeConditionVariable &&
|
if (PInitializeConditionVariable_ && PSleepConditionVariableCS_
|
||||||
_PSleepConditionVariableCS &&
|
&& PWakeConditionVariable_ && PWakeAllConditionVariable_) {
|
||||||
_PWakeConditionVariable &&
|
WEBRTC_TRACE(
|
||||||
_PWakeAllConditionVariable)
|
kTraceStateInfo, kTraceUtility, -1,
|
||||||
{
|
"Loaded native condition variables");
|
||||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
win_support_condition_variables_primitive_ = true;
|
||||||
"Loaded native condition variables");
|
}
|
||||||
_winSupportConditionVariablesPrimitive = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_winSupportConditionVariablesPrimitive)
|
if (win_support_condition_variables_primitive_) {
|
||||||
{
|
PInitializeConditionVariable_(&condition_variable_);
|
||||||
_PInitializeConditionVariable(&_conditionVariable);
|
|
||||||
|
|
||||||
_events[WAKEALL_0] = NULL;
|
events_[WAKEALL_0] = NULL;
|
||||||
_events[WAKEALL_1] = NULL;
|
events_[WAKEALL_1] = NULL;
|
||||||
_events[WAKE] = NULL;
|
events_[WAKE] = NULL;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
memset(&_numWaiters[0],0,sizeof(_numWaiters));
|
memset(&num_waiters_[0], 0, sizeof(num_waiters_));
|
||||||
|
|
||||||
InitializeCriticalSection(&_numWaitersCritSect);
|
InitializeCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
|
||||||
_events[WAKEALL_0] = CreateEvent(NULL, // no security attributes
|
events_[WAKEALL_0] = CreateEvent(NULL, // no security attributes
|
||||||
TRUE, // manual-reset, sticky event
|
TRUE, // manual-reset, sticky event
|
||||||
FALSE, // initial state non-signaled
|
FALSE, // initial state non-signaled
|
||||||
NULL); // no name for event
|
NULL); // no name for event
|
||||||
|
|
||||||
_events[WAKEALL_1] = CreateEvent(NULL, // no security attributes
|
events_[WAKEALL_1] = CreateEvent(NULL, // no security attributes
|
||||||
TRUE, // manual-reset, sticky event
|
TRUE, // manual-reset, sticky event
|
||||||
FALSE, // initial state non-signaled
|
FALSE, // initial state non-signaled
|
||||||
NULL); // no name for event
|
NULL); // no name for event
|
||||||
|
|
||||||
_events[WAKE] = CreateEvent(NULL, // no security attributes
|
events_[WAKE] = CreateEvent(NULL, // no security attributes
|
||||||
FALSE, // auto-reset, sticky event
|
FALSE, // auto-reset, sticky event
|
||||||
FALSE, // initial state non-signaled
|
FALSE, // initial state non-signaled
|
||||||
NULL); // no name for event
|
NULL); // no name for event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConditionVariableWindows::~ConditionVariableWindows()
|
ConditionVariableWindows::~ConditionVariableWindows() {
|
||||||
{
|
if (!win_support_condition_variables_primitive_) {
|
||||||
if(!_winSupportConditionVariablesPrimitive)
|
CloseHandle(events_[WAKE]);
|
||||||
{
|
CloseHandle(events_[WAKEALL_1]);
|
||||||
CloseHandle(_events[WAKE]);
|
CloseHandle(events_[WAKEALL_0]);
|
||||||
CloseHandle(_events[WAKEALL_1]);
|
|
||||||
CloseHandle(_events[WAKEALL_0]);
|
|
||||||
|
|
||||||
DeleteCriticalSection(&_numWaitersCritSect);
|
DeleteCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConditionVariableWindows::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||||
|
SleepCS(crit_sect, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConditionVariableWindows::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||||
|
unsigned long max_time_in_ms) {
|
||||||
|
CriticalSectionWindows* cs =
|
||||||
|
reinterpret_cast<CriticalSectionWindows*>(&crit_sect);
|
||||||
|
|
||||||
|
if (win_support_condition_variables_primitive_) {
|
||||||
|
BOOL ret_val = PSleepConditionVariableCS_(
|
||||||
|
&condition_variable_, &(cs->crit), max_time_in_ms);
|
||||||
|
return (ret_val == 0) ? false : true;
|
||||||
|
} else {
|
||||||
|
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
|
||||||
|
// Get the eventID for the event that will be triggered by next
|
||||||
|
// WakeAll() call and start waiting for it.
|
||||||
|
const EventWakeUpType eventID =
|
||||||
|
(WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
|
||||||
|
|
||||||
|
++(num_waiters_[eventID]);
|
||||||
|
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
|
||||||
|
LeaveCriticalSection(&cs->crit);
|
||||||
|
HANDLE events[2];
|
||||||
|
events[0] = events_[WAKE];
|
||||||
|
events[1] = events_[eventID];
|
||||||
|
const DWORD result = WaitForMultipleObjects(2, // Wait on 2 events.
|
||||||
|
events, FALSE, // Wait for either.
|
||||||
|
max_time_in_ms);
|
||||||
|
|
||||||
|
const bool ret_val = (result != WAIT_TIMEOUT);
|
||||||
|
|
||||||
|
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
--(num_waiters_[eventID]);
|
||||||
|
|
||||||
|
// Last waiter should only be true for WakeAll(). WakeAll() correspond
|
||||||
|
// to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1)
|
||||||
|
const bool last_waiter = (result == WAIT_OBJECT_0 + 1)
|
||||||
|
&& (num_waiters_[eventID] == 0);
|
||||||
|
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
|
||||||
|
if (last_waiter) {
|
||||||
|
// Reset/unset the WakeAll() event since all threads have been
|
||||||
|
// released.
|
||||||
|
ResetEvent(events_[eventID]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnterCriticalSection(&cs->crit);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect)
|
void ConditionVariableWindows::Wake() {
|
||||||
{
|
if (win_support_condition_variables_primitive_) {
|
||||||
SleepCS(critSect, INFINITE);
|
PWakeConditionVariable_(&condition_variable_);
|
||||||
}
|
} else {
|
||||||
|
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
const bool have_waiters = (num_waiters_[WAKEALL_0] > 0)
|
||||||
|
|| (num_waiters_[WAKEALL_1] > 0);
|
||||||
|
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
|
||||||
bool ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect,
|
if (have_waiters) {
|
||||||
unsigned long maxTimeInMS)
|
SetEvent(events_[WAKE]);
|
||||||
{
|
|
||||||
CriticalSectionWindows* cs = reinterpret_cast<CriticalSectionWindows*>(
|
|
||||||
&critSect);
|
|
||||||
|
|
||||||
if(_winSupportConditionVariablesPrimitive)
|
|
||||||
{
|
|
||||||
BOOL retVal = _PSleepConditionVariableCS(&_conditionVariable,
|
|
||||||
&(cs->crit),maxTimeInMS);
|
|
||||||
return (retVal == 0) ? false : true;
|
|
||||||
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&_numWaitersCritSect);
|
|
||||||
// Get the eventID for the event that will be triggered by next
|
|
||||||
// WakeAll() call and start waiting for it.
|
|
||||||
const EventWakeUpType eventID = (WAKEALL_0 == _eventID) ?
|
|
||||||
WAKEALL_1 : WAKEALL_0;
|
|
||||||
++(_numWaiters[eventID]);
|
|
||||||
LeaveCriticalSection(&_numWaitersCritSect);
|
|
||||||
|
|
||||||
LeaveCriticalSection(&cs->crit);
|
|
||||||
HANDLE events[2];
|
|
||||||
events[0] = _events[WAKE];
|
|
||||||
events[1] = _events[eventID];
|
|
||||||
const DWORD result = WaitForMultipleObjects(2, // Wait on 2 events.
|
|
||||||
events,
|
|
||||||
FALSE, // Wait for either.
|
|
||||||
maxTimeInMS);
|
|
||||||
|
|
||||||
const bool retVal = (result != WAIT_TIMEOUT);
|
|
||||||
|
|
||||||
EnterCriticalSection(&_numWaitersCritSect);
|
|
||||||
--(_numWaiters[eventID]);
|
|
||||||
// Last waiter should only be true for WakeAll(). WakeAll() correspond
|
|
||||||
// to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1)
|
|
||||||
const bool lastWaiter = (result == WAIT_OBJECT_0 + 1) &&
|
|
||||||
(_numWaiters[eventID] == 0);
|
|
||||||
LeaveCriticalSection(&_numWaitersCritSect);
|
|
||||||
|
|
||||||
if (lastWaiter)
|
|
||||||
{
|
|
||||||
// Reset/unset the WakeAll() event since all threads have been
|
|
||||||
// released.
|
|
||||||
ResetEvent(_events[eventID]);
|
|
||||||
}
|
|
||||||
|
|
||||||
EnterCriticalSection(&cs->crit);
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ConditionVariableWindows::WakeAll() {
|
||||||
ConditionVariableWindows::Wake()
|
if (win_support_condition_variables_primitive_) {
|
||||||
{
|
PWakeAllConditionVariable_(&condition_variable_);
|
||||||
if(_winSupportConditionVariablesPrimitive)
|
} else {
|
||||||
{
|
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||||
_PWakeConditionVariable(&_conditionVariable);
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&_numWaitersCritSect);
|
|
||||||
const bool haveWaiters = (_numWaiters[WAKEALL_0] > 0) ||
|
|
||||||
(_numWaiters[WAKEALL_1] > 0);
|
|
||||||
LeaveCriticalSection(&_numWaitersCritSect);
|
|
||||||
|
|
||||||
if (haveWaiters)
|
// Update current WakeAll() event
|
||||||
{
|
eventID_ = (WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
|
||||||
SetEvent(_events[WAKE]);
|
|
||||||
}
|
// Trigger current event
|
||||||
|
const EventWakeUpType eventID = eventID_;
|
||||||
|
const bool have_waiters = num_waiters_[eventID] > 0;
|
||||||
|
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||||
|
|
||||||
|
if (have_waiters) {
|
||||||
|
SetEvent(events_[eventID]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ConditionVariableWindows::WakeAll()
|
|
||||||
{
|
|
||||||
if(_winSupportConditionVariablesPrimitive)
|
|
||||||
{
|
|
||||||
_PWakeAllConditionVariable(&_conditionVariable);
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&_numWaitersCritSect);
|
|
||||||
// Update current WakeAll() event
|
|
||||||
_eventID = (WAKEALL_0 == _eventID) ? WAKEALL_1 : WAKEALL_0;
|
|
||||||
// Trigger current event
|
|
||||||
const EventWakeUpType eventID = _eventID;
|
|
||||||
const bool haveWaiters = _numWaiters[eventID] > 0;
|
|
||||||
LeaveCriticalSection(&_numWaitersCritSect);
|
|
||||||
|
|
||||||
if (haveWaiters)
|
|
||||||
{
|
|
||||||
SetEvent(_events[eventID]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -8,60 +8,58 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
|
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WIN_H_
|
||||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
|
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WIN_H_
|
||||||
|
|
||||||
#include "condition_variable_wrapper.h"
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
namespace webrtc {
|
#include "condition_variable_wrapper.h"
|
||||||
#if !defined CONDITION_VARIABLE_INIT
|
|
||||||
typedef struct _RTL_CONDITION_VARIABLE
|
|
||||||
{
|
|
||||||
void* Ptr;
|
|
||||||
} RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
|
|
||||||
|
|
||||||
typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
|
namespace webrtc {
|
||||||
|
|
||||||
|
#if !defined CONDITION_VARIABLE_INIT
|
||||||
|
typedef struct RTL_CONDITION_VARIABLE_ {
|
||||||
|
void* Ptr;
|
||||||
|
} RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
|
||||||
|
|
||||||
|
typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
typedef void (WINAPI* PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
||||||
typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
typedef BOOL (WINAPI* PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||||
PCRITICAL_SECTION, DWORD);
|
PCRITICAL_SECTION, DWORD);
|
||||||
typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
|
typedef void (WINAPI* PWakeConditionVariable)(PCONDITION_VARIABLE);
|
||||||
typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
typedef void (WINAPI* PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||||
|
|
||||||
|
class ConditionVariableWindows : public ConditionVariableWrapper {
|
||||||
|
public:
|
||||||
|
ConditionVariableWindows();
|
||||||
|
~ConditionVariableWindows();
|
||||||
|
|
||||||
class ConditionVariableWindows : public ConditionVariableWrapper
|
void SleepCS(CriticalSectionWrapper& crit_sect);
|
||||||
{
|
bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS);
|
||||||
public:
|
void Wake();
|
||||||
ConditionVariableWindows();
|
void WakeAll();
|
||||||
~ConditionVariableWindows();
|
|
||||||
|
|
||||||
void SleepCS(CriticalSectionWrapper& critSect);
|
private:
|
||||||
bool SleepCS(CriticalSectionWrapper& critSect, unsigned long maxTimeInMS);
|
enum EventWakeUpType {
|
||||||
void Wake();
|
WAKEALL_0 = 0,
|
||||||
void WakeAll();
|
WAKEALL_1 = 1,
|
||||||
|
WAKE = 2,
|
||||||
|
EVENT_COUNT = 3
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum EventWakeUpType
|
// Native support for Windows Vista+
|
||||||
{
|
static bool win_support_condition_variables_primitive_;
|
||||||
WAKEALL_0 = 0,
|
CONDITION_VARIABLE condition_variable_;
|
||||||
WAKEALL_1 = 1,
|
|
||||||
WAKE = 2,
|
|
||||||
EVENT_COUNT = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
unsigned int num_waiters_[2];
|
||||||
// Native support for Windows Vista+
|
EventWakeUpType eventID_;
|
||||||
static bool _winSupportConditionVariablesPrimitive;
|
CRITICAL_SECTION num_waiters_crit_sect_;
|
||||||
CONDITION_VARIABLE _conditionVariable;
|
HANDLE events_[EVENT_COUNT];
|
||||||
|
|
||||||
unsigned int _numWaiters[2];
|
|
||||||
EventWakeUpType _eventID;
|
|
||||||
CRITICAL_SECTION _numWaitersCritSect;
|
|
||||||
HANDLE _events[EVENT_COUNT];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
|
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WIN_H_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user