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:
phoglund@webrtc.org 2012-11-14 09:55:04 +00:00
parent 12b828ac90
commit a36d75a03c
7 changed files with 309 additions and 358 deletions

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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_