Split condition_variable_win.cc into native (for Vista and newer OS versions) and generic implementation (based on events).
Note that this means that there is no new code. The code has been taken directly from condition_variable_win.cc/h compensating minimally to be able to split up the two code paths. Tested by: 1) Disabling native implementation and send to try bots. 2) Only return native implementation (i.e. if native implementation returns NULL there will be a crash when using the condition variable) and send to try bots. 3) The final cl sent to trybots. All tests pass. The changes are due to static analyzer code complaints. BUG=N/A Review URL: https://webrtc-codereview.appspot.com/1191004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3728 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
1b31c78e5f
commit
686001dd96
@ -8,21 +8,29 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "condition_variable_win.h"
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/source/condition_variable_event_win.h"
|
||||
#include "webrtc/system_wrappers/source/condition_variable_native_win.h"
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
#include <pthread.h>
|
||||
#include "condition_variable_posix.h"
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/source/condition_variable_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ConditionVariableWrapper* ConditionVariableWrapper::CreateConditionVariable() {
|
||||
#if defined(_WIN32)
|
||||
return new ConditionVariableWindows;
|
||||
// Try to create native condition variable implementation.
|
||||
ConditionVariableWrapper* ret_val = ConditionVariableNativeWin::Create();
|
||||
if (!ret_val) {
|
||||
// Native condition variable implementation does not exist. Create generic
|
||||
// condition variable based on events.
|
||||
ret_val = new ConditionVariableEventWin();
|
||||
}
|
||||
return ret_val;
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
return ConditionVariablePosix::Create();
|
||||
#else
|
||||
|
127
webrtc/system_wrappers/source/condition_variable_event_win.cc
Normal file
127
webrtc/system_wrappers/source/condition_variable_event_win.cc
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Use of this source code is governed by the ACE copyright license which
|
||||
* can be found in the LICENSE file in the third_party_mods/ace directory of
|
||||
* the source tree or at http://www1.cse.wustl.edu/~schmidt/ACE-copying.html.
|
||||
*/
|
||||
/*
|
||||
* This source code contain modifications to the original source code
|
||||
* which can be found here:
|
||||
* http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (section 3.2).
|
||||
* Modifications:
|
||||
* 1) Dynamic detection of native support for condition variables.
|
||||
* 2) Use of WebRTC defined types and classes. Renaming of some functions.
|
||||
* 3) Introduction of a second event for wake all functionality. This prevents
|
||||
* a thread from spinning on the same condition variable, preventing other
|
||||
* threads from waking up.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/condition_variable_event_win.h"
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ConditionVariableEventWin::ConditionVariableEventWin() : eventID_(WAKEALL_0) {
|
||||
memset(&num_waiters_[0], 0, sizeof(num_waiters_));
|
||||
|
||||
InitializeCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
events_[WAKEALL_0] = CreateEvent(NULL, // no security attributes
|
||||
TRUE, // manual-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
|
||||
events_[WAKEALL_1] = CreateEvent(NULL, // no security attributes
|
||||
TRUE, // manual-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
|
||||
events_[WAKE] = CreateEvent(NULL, // no security attributes
|
||||
FALSE, // auto-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
}
|
||||
|
||||
ConditionVariableEventWin::~ConditionVariableEventWin() {
|
||||
CloseHandle(events_[WAKE]);
|
||||
CloseHandle(events_[WAKEALL_1]);
|
||||
CloseHandle(events_[WAKEALL_0]);
|
||||
|
||||
DeleteCriticalSection(&num_waiters_crit_sect_);
|
||||
}
|
||||
|
||||
void ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||
SleepCS(crit_sect, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_in_ms) {
|
||||
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_);
|
||||
|
||||
CriticalSectionWindows* cs =
|
||||
static_cast<CriticalSectionWindows*>(&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 ConditionVariableEventWin::Wake() {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
const bool have_waiters = (num_waiters_[WAKEALL_0] > 0) ||
|
||||
(num_waiters_[WAKEALL_1] > 0);
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
if (have_waiters) {
|
||||
SetEvent(events_[WAKE]);
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionVariableEventWin::WakeAll() {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
// Update current WakeAll() event
|
||||
eventID_ = (WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
|
||||
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
46
webrtc/system_wrappers/source/condition_variable_event_win.h
Normal file
46
webrtc/system_wrappers/source/condition_variable_event_win.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2013 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 WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ConditionVariableEventWin : public ConditionVariableWrapper {
|
||||
public:
|
||||
ConditionVariableEventWin();
|
||||
virtual ~ConditionVariableEventWin();
|
||||
|
||||
void SleepCS(CriticalSectionWrapper& crit_sect);
|
||||
bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS);
|
||||
void Wake();
|
||||
void WakeAll();
|
||||
|
||||
private:
|
||||
enum EventWakeUpType {
|
||||
WAKEALL_0 = 0,
|
||||
WAKEALL_1 = 1,
|
||||
WAKE = 2,
|
||||
EVENT_COUNT = 3
|
||||
};
|
||||
|
||||
unsigned int num_waiters_[2];
|
||||
EventWakeUpType eventID_;
|
||||
CRITICAL_SECTION num_waiters_crit_sect_;
|
||||
HANDLE events_[EVENT_COUNT];
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
105
webrtc/system_wrappers/source/condition_variable_native_win.cc
Normal file
105
webrtc/system_wrappers/source/condition_variable_native_win.cc
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2013 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 "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/system_wrappers/source/condition_variable_native_win.h"
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static HMODULE library = NULL;
|
||||
|
||||
PInitializeConditionVariable PInitializeConditionVariable_;
|
||||
PSleepConditionVariableCS PSleepConditionVariableCS_;
|
||||
PWakeConditionVariable PWakeConditionVariable_;
|
||||
PWakeAllConditionVariable PWakeAllConditionVariable_;
|
||||
|
||||
typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||
PCRITICAL_SECTION, DWORD);
|
||||
typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||
|
||||
ConditionVariableNativeWin::ConditionVariableNativeWin() {
|
||||
}
|
||||
|
||||
ConditionVariableNativeWin::~ConditionVariableNativeWin() {
|
||||
}
|
||||
|
||||
ConditionVariableWrapper* ConditionVariableNativeWin::Create() {
|
||||
ConditionVariableNativeWin* ret_val = new ConditionVariableNativeWin();
|
||||
if (!ret_val->Init()) {
|
||||
delete ret_val;
|
||||
return NULL;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
bool ConditionVariableNativeWin::Init() {
|
||||
bool win_support_condition_variables_primitive = true;
|
||||
if (!library) {
|
||||
// Native implementation is supported on Vista+.
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
// TODO(henrike): this code results in an attempt to load the above dll
|
||||
// every time the previous attempt failed. Only try to load once.
|
||||
if (library) {
|
||||
// TODO(henrike): not thread safe as reading and writing to library is not
|
||||
// serialized. Fix.
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
|
||||
|
||||
PInitializeConditionVariable_ =
|
||||
(PInitializeConditionVariable) GetProcAddress(
|
||||
library, "InitializeConditionVariable");
|
||||
PSleepConditionVariableCS_ = (PSleepConditionVariableCS) GetProcAddress(
|
||||
library, "SleepConditionVariableCS");
|
||||
PWakeConditionVariable_ = (PWakeConditionVariable) GetProcAddress(
|
||||
library, "WakeConditionVariable");
|
||||
PWakeAllConditionVariable_ = (PWakeAllConditionVariable) GetProcAddress(
|
||||
library, "WakeAllConditionVariable");
|
||||
|
||||
if (PInitializeConditionVariable_ && PSleepConditionVariableCS_
|
||||
&& PWakeConditionVariable_ && PWakeAllConditionVariable_) {
|
||||
WEBRTC_TRACE(
|
||||
kTraceStateInfo, kTraceUtility, -1,
|
||||
"Loaded native condition variables");
|
||||
} else {
|
||||
win_support_condition_variables_primitive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!win_support_condition_variables_primitive) {
|
||||
return false;
|
||||
}
|
||||
PInitializeConditionVariable_(&condition_variable_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||
SleepCS(crit_sect, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_in_ms) {
|
||||
CriticalSectionWindows* cs =
|
||||
static_cast<CriticalSectionWindows*>(&crit_sect);
|
||||
BOOL ret_val = PSleepConditionVariableCS_(&condition_variable_,
|
||||
&(cs->crit), max_time_in_ms);
|
||||
return ret_val != 0;
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::Wake() {
|
||||
PWakeConditionVariable_(&condition_variable_);
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::WakeAll() {
|
||||
PWakeAllConditionVariable_(&condition_variable_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
* Copyright (c) 2013 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
|
||||
@ -8,12 +8,12 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WIN_H_
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -31,10 +31,10 @@ typedef BOOL (WINAPI* PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||
typedef void (WINAPI* PWakeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef void (WINAPI* PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||
|
||||
class ConditionVariableWindows : public ConditionVariableWrapper {
|
||||
class ConditionVariableNativeWin : public ConditionVariableWrapper {
|
||||
public:
|
||||
ConditionVariableWindows();
|
||||
~ConditionVariableWindows();
|
||||
static ConditionVariableWrapper* Create();
|
||||
virtual ~ConditionVariableNativeWin();
|
||||
|
||||
void SleepCS(CriticalSectionWrapper& crit_sect);
|
||||
bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS);
|
||||
@ -42,24 +42,13 @@ class ConditionVariableWindows : public ConditionVariableWrapper {
|
||||
void WakeAll();
|
||||
|
||||
private:
|
||||
enum EventWakeUpType {
|
||||
WAKEALL_0 = 0,
|
||||
WAKEALL_1 = 1,
|
||||
WAKE = 2,
|
||||
EVENT_COUNT = 3
|
||||
};
|
||||
ConditionVariableNativeWin();
|
||||
|
||||
private:
|
||||
// Native support for Windows Vista+
|
||||
static bool win_support_condition_variables_primitive_;
|
||||
CONDITION_VARIABLE condition_variable_;
|
||||
bool Init();
|
||||
|
||||
unsigned int num_waiters_[2];
|
||||
EventWakeUpType eventID_;
|
||||
CRITICAL_SECTION num_waiters_crit_sect_;
|
||||
HANDLE events_[EVENT_COUNT];
|
||||
CONDITION_VARIABLE condition_variable_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WIN_H_
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Use of this source code is governed by the ACE copyright license which
|
||||
* can be found in the LICENSE file in the third_party_mods/ace directory of
|
||||
* the source tree or at http://www1.cse.wustl.edu/~schmidt/ACE-copying.html.
|
||||
*/
|
||||
/*
|
||||
* This source code contain modifications to the original source code
|
||||
* which can be found here:
|
||||
* http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (section 3.2).
|
||||
* Modifications:
|
||||
* 1) Dynamic detection of native support for condition variables.
|
||||
* 2) Use of WebRTC defined types and classes. Renaming of some functions.
|
||||
* 3) Introduction of a second event for wake all functionality. This prevents
|
||||
* a thread from spinning on the same condition variable, preventing other
|
||||
* threads from waking up.
|
||||
*/
|
||||
|
||||
// TODO (hellner): probably nicer to split up native and generic
|
||||
// implementation into two different files
|
||||
|
||||
#include "condition_variable_win.h"
|
||||
#include "critical_section_win.h"
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
bool ConditionVariableWindows::win_support_condition_variables_primitive_ =
|
||||
false;
|
||||
static HMODULE library = NULL;
|
||||
|
||||
PInitializeConditionVariable PInitializeConditionVariable_;
|
||||
PSleepConditionVariableCS PSleepConditionVariableCS_;
|
||||
PWakeConditionVariable PWakeConditionVariable_;
|
||||
PWakeAllConditionVariable PWakeAllConditionVariable_;
|
||||
|
||||
typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||
PCRITICAL_SECTION, DWORD);
|
||||
typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||
|
||||
ConditionVariableWindows::ConditionVariableWindows()
|
||||
: eventID_(WAKEALL_0) {
|
||||
if (!library) {
|
||||
// Use native implementation if supported (i.e Vista+)
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
if (library) {
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
|
||||
|
||||
PInitializeConditionVariable_ =
|
||||
(PInitializeConditionVariable) GetProcAddress(
|
||||
library, "InitializeConditionVariable");
|
||||
PSleepConditionVariableCS_ = (PSleepConditionVariableCS) GetProcAddress(
|
||||
library, "SleepConditionVariableCS");
|
||||
PWakeConditionVariable_ = (PWakeConditionVariable) GetProcAddress(
|
||||
library, "WakeConditionVariable");
|
||||
PWakeAllConditionVariable_ = (PWakeAllConditionVariable) GetProcAddress(
|
||||
library, "WakeAllConditionVariable");
|
||||
|
||||
if (PInitializeConditionVariable_ && PSleepConditionVariableCS_
|
||||
&& PWakeConditionVariable_ && PWakeAllConditionVariable_) {
|
||||
WEBRTC_TRACE(
|
||||
kTraceStateInfo, kTraceUtility, -1,
|
||||
"Loaded native condition variables");
|
||||
win_support_condition_variables_primitive_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (win_support_condition_variables_primitive_) {
|
||||
PInitializeConditionVariable_(&condition_variable_);
|
||||
|
||||
events_[WAKEALL_0] = NULL;
|
||||
events_[WAKEALL_1] = NULL;
|
||||
events_[WAKE] = NULL;
|
||||
|
||||
} else {
|
||||
memset(&num_waiters_[0], 0, sizeof(num_waiters_));
|
||||
|
||||
InitializeCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
events_[WAKEALL_0] = CreateEvent(NULL, // no security attributes
|
||||
TRUE, // manual-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
|
||||
events_[WAKEALL_1] = CreateEvent(NULL, // no security attributes
|
||||
TRUE, // manual-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
|
||||
events_[WAKE] = CreateEvent(NULL, // no security attributes
|
||||
FALSE, // auto-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
}
|
||||
}
|
||||
|
||||
ConditionVariableWindows::~ConditionVariableWindows() {
|
||||
if (!win_support_condition_variables_primitive_) {
|
||||
CloseHandle(events_[WAKE]);
|
||||
CloseHandle(events_[WAKEALL_1]);
|
||||
CloseHandle(events_[WAKEALL_0]);
|
||||
|
||||
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::Wake() {
|
||||
if (win_support_condition_variables_primitive_) {
|
||||
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_);
|
||||
|
||||
if (have_waiters) {
|
||||
SetEvent(events_[WAKE]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionVariableWindows::WakeAll() {
|
||||
if (win_support_condition_variables_primitive_) {
|
||||
PWakeAllConditionVariable_(&condition_variable_);
|
||||
} else {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
// Update current WakeAll() event
|
||||
eventID_ = (WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
|
||||
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -29,7 +29,8 @@ class CriticalSectionWindows : public CriticalSectionWrapper {
|
||||
private:
|
||||
CRITICAL_SECTION crit;
|
||||
|
||||
friend class ConditionVariableWindows;
|
||||
friend class ConditionVariableEventWin;
|
||||
friend class ConditionVariableNativeWin;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -61,8 +61,10 @@
|
||||
'condition_variable.cc',
|
||||
'condition_variable_posix.cc',
|
||||
'condition_variable_posix.h',
|
||||
'condition_variable_win.cc',
|
||||
'condition_variable_win.h',
|
||||
'condition_variable_event_win.cc',
|
||||
'condition_variable_event_win.h',
|
||||
'condition_variable_native_win.cc',
|
||||
'condition_variable_native_win.h',
|
||||
'cpu.cc',
|
||||
'cpu_no_op.cc',
|
||||
'cpu_info.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user