1a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin/* 2a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * Use of this source code is governed by the ACE copyright license which 3a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * can be found in the LICENSE file in the third_party_mods/ace directory of 4a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * the source tree or at http://www1.cse.wustl.edu/~schmidt/ACE-copying.html. 5a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin */ 6a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin/* 7a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * This source code contain modifications to the original source code 8a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * which can be found here: 9a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (section 3.2). 10a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * Modifications: 11a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * 1) Dynamic detection of native support for condition variables. 12a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * 2) Use of WebRTC defined types and classes. Renaming of some functions. 13a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * 3) Introduction of a second event for wake all functionality. This prevents 14a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * a thread from spinning on the same condition variable, preventing other 15a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * threads from waking up. 16a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin */ 17a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 18a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// TODO (hellner): probably nicer to split up native and generic 19a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// implementation into two different files 20a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 21a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "condition_variable_win.h" 22a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 23a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "critical_section_win.h" 24a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "trace.h" 25a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 26a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinnamespace webrtc { 27a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ConditionVariableWindows::_winSupportConditionVariablesPrimitive = false; 28a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinstatic HMODULE library = NULL; 29a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 30a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPInitializeConditionVariable _PInitializeConditionVariable; 31a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPSleepConditionVariableCS _PSleepConditionVariableCS; 32a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPWakeConditionVariable _PWakeConditionVariable; 33a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPWakeAllConditionVariable _PWakeAllConditionVariable; 34a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 35a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkintypedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE); 36a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkintypedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE, 37a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin PCRITICAL_SECTION, DWORD); 38a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkintypedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE); 39a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkintypedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE); 40a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 41a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinConditionVariableWindows::ConditionVariableWindows() 42a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin : _eventID(WAKEALL_0) 43a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 44a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (!library) 45a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 46a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Use native implementation if supported (i.e Vista+) 47a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin library = LoadLibrary(TEXT("Kernel32.dll")); 48a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (library) 49a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 50a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, 51a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "Loaded Kernel.dll"); 52a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 53a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PInitializeConditionVariable = 54a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin (PInitializeConditionVariable) GetProcAddress( 55a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin library, 56a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "InitializeConditionVariable"); 57a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PSleepConditionVariableCS = 58a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin (PSleepConditionVariableCS)GetProcAddress( 59a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin library, 60a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "SleepConditionVariableCS"); 61a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PWakeConditionVariable = 62a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin (PWakeConditionVariable)GetProcAddress( 63a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin library, 64a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "WakeConditionVariable"); 65a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PWakeAllConditionVariable = 66a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin (PWakeAllConditionVariable)GetProcAddress( 67a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin library, 68a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "WakeAllConditionVariable"); 69a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 70a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if(_PInitializeConditionVariable && 71a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PSleepConditionVariableCS && 72a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PWakeConditionVariable && 73a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PWakeAllConditionVariable) 74a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 75a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, 76a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "Loaded native condition variables"); 77a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _winSupportConditionVariablesPrimitive = true; 78a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 79a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 80a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 81a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 82a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_winSupportConditionVariablesPrimitive) 83a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 84a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PInitializeConditionVariable(&_conditionVariable); 85a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 86a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _events[WAKEALL_0] = NULL; 87a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _events[WAKEALL_1] = NULL; 88a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _events[WAKE] = NULL; 89a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 90a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } else { 91a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin memset(&_numWaiters[0],0,sizeof(_numWaiters)); 92a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 93a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin InitializeCriticalSection(&_numWaitersCritSect); 94a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 95a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _events[WAKEALL_0] = CreateEvent(NULL, // no security attributes 96a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin TRUE, // manual-reset, sticky event 97a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin FALSE, // initial state non-signaled 98a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin NULL); // no name for event 99a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 100a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _events[WAKEALL_1] = CreateEvent(NULL, // no security attributes 101a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin TRUE, // manual-reset, sticky event 102a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin FALSE, // initial state non-signaled 103a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin NULL); // no name for event 104a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 105a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _events[WAKE] = CreateEvent(NULL, // no security attributes 106a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin FALSE, // auto-reset, sticky event 107a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin FALSE, // initial state non-signaled 108a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin NULL); // no name for event 109a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 110a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 111a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 112a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinConditionVariableWindows::~ConditionVariableWindows() 113a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 114a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if(!_winSupportConditionVariablesPrimitive) 115a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 116a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CloseHandle(_events[WAKE]); 117a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CloseHandle(_events[WAKEALL_1]); 118a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CloseHandle(_events[WAKEALL_0]); 119a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 120a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin DeleteCriticalSection(&_numWaitersCritSect); 121a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 122a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 123a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 124a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect) 125a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 126a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SleepCS(critSect, INFINITE); 127a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 128a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 129a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect, 130a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin unsigned long maxTimeInMS) 131a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 132a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CriticalSectionWindows* cs = reinterpret_cast<CriticalSectionWindows*>( 133a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin &critSect); 134a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 135a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if(_winSupportConditionVariablesPrimitive) 136a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 137a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin BOOL retVal = _PSleepConditionVariableCS(&_conditionVariable, 138a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin &(cs->crit),maxTimeInMS); 139a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return (retVal == 0) ? false : true; 140a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 141a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin }else 142a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 143a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin EnterCriticalSection(&_numWaitersCritSect); 144a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Get the eventID for the event that will be triggered by next 145a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // WakeAll() call and start waiting for it. 146a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const EventWakeUpType eventID = (WAKEALL_0 == _eventID) ? 147a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin WAKEALL_1 : WAKEALL_0; 148a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin ++(_numWaiters[eventID]); 149a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin LeaveCriticalSection(&_numWaitersCritSect); 150a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 151a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin LeaveCriticalSection(&cs->crit); 152a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin HANDLE events[2]; 153a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin events[0] = _events[WAKE]; 154a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin events[1] = _events[eventID]; 155a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const DWORD result = WaitForMultipleObjects(2, // Wait on 2 events. 156a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin events, 157a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin FALSE, // Wait for either. 158a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin maxTimeInMS); 159a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 160a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const bool retVal = (result != WAIT_TIMEOUT); 161a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 162a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin EnterCriticalSection(&_numWaitersCritSect); 163a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin --(_numWaiters[eventID]); 164a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Last waiter should only be true for WakeAll(). WakeAll() correspond 165a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1) 166a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const bool lastWaiter = (result == WAIT_OBJECT_0 + 1) && 167a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin (_numWaiters[eventID] == 0); 168a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin LeaveCriticalSection(&_numWaitersCritSect); 169a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 170a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (lastWaiter) 171a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 172a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Reset/unset the WakeAll() event since all threads have been 173a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // released. 174a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin ResetEvent(_events[eventID]); 175a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 176a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 177a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin EnterCriticalSection(&cs->crit); 178a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return retVal; 179a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 180a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 181a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 182a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid 183a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinConditionVariableWindows::Wake() 184a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 185a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if(_winSupportConditionVariablesPrimitive) 186a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 187a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PWakeConditionVariable(&_conditionVariable); 188a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin }else 189a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 190a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin EnterCriticalSection(&_numWaitersCritSect); 191a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const bool haveWaiters = (_numWaiters[WAKEALL_0] > 0) || 192a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin (_numWaiters[WAKEALL_1] > 0); 193a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin LeaveCriticalSection(&_numWaitersCritSect); 194a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 195a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (haveWaiters) 196a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 197a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SetEvent(_events[WAKE]); 198a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 199a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 200a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 201a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 202a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid 203a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinConditionVariableWindows::WakeAll() 204a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 205a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if(_winSupportConditionVariablesPrimitive) 206a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 207a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _PWakeAllConditionVariable(&_conditionVariable); 208a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin }else 209a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 210a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin EnterCriticalSection(&_numWaitersCritSect); 211a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Update current WakeAll() event 212a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _eventID = (WAKEALL_0 == _eventID) ? WAKEALL_1 : WAKEALL_0; 213a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Trigger current event 214a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const EventWakeUpType eventID = _eventID; 215a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const bool haveWaiters = _numWaiters[eventID] > 0; 216a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin LeaveCriticalSection(&_numWaitersCritSect); 217a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 218a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (haveWaiters) 219a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 220a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SetEvent(_events[eventID]); 221a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 222a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 223a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 224a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} // namespace webrtc 225