1/* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "rw_lock_win.h" 12 13#include "critical_section_wrapper.h" 14#include "condition_variable_wrapper.h" 15#include "trace.h" 16 17// TODO (hellner) why not just use the rw_lock_generic.cc solution if 18// native is not supported? Unnecessary redundancy! 19 20namespace webrtc { 21bool RWLockWindows::_winSupportRWLockPrimitive = false; 22static HMODULE library = NULL; 23 24PInitializeSRWLock _PInitializeSRWLock; 25PAcquireSRWLockExclusive _PAcquireSRWLockExclusive; 26PAcquireSRWLockShared _PAcquireSRWLockShared; 27PReleaseSRWLockShared _PReleaseSRWLockShared; 28PReleaseSRWLockExclusive _PReleaseSRWLockExclusive; 29 30RWLockWindows::RWLockWindows() 31 : _critSectPtr(NULL), 32 _readCondPtr(NULL), 33 _writeCondPtr(NULL), 34 _readersActive(0), 35 _writerActive(false), 36 _readersWaiting(0), 37 _writersWaiting(0) 38{ 39} 40 41RWLockWindows::~RWLockWindows() 42{ 43 delete _writeCondPtr; 44 delete _readCondPtr; 45 delete _critSectPtr; 46} 47 48int RWLockWindows::Init() 49{ 50 if(!library) 51 { 52 // Use native implementation if supported (i.e Vista+) 53 library = LoadLibrary(TEXT("Kernel32.dll")); 54 if(library) 55 { 56 WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, 57 "Loaded Kernel.dll"); 58 59 _PInitializeSRWLock = 60 (PInitializeSRWLock)GetProcAddress( 61 library, 62 "InitializeSRWLock"); 63 64 _PAcquireSRWLockExclusive = 65 (PAcquireSRWLockExclusive)GetProcAddress( 66 library, 67 "AcquireSRWLockExclusive"); 68 _PReleaseSRWLockExclusive = 69 (PReleaseSRWLockExclusive)GetProcAddress( 70 library, 71 "ReleaseSRWLockExclusive"); 72 _PAcquireSRWLockShared = 73 (PAcquireSRWLockShared)GetProcAddress( 74 library, 75 "AcquireSRWLockShared"); 76 _PReleaseSRWLockShared = 77 (PReleaseSRWLockShared)GetProcAddress( 78 library, 79 "ReleaseSRWLockShared"); 80 81 if( _PInitializeSRWLock && 82 _PAcquireSRWLockExclusive && 83 _PReleaseSRWLockExclusive && 84 _PAcquireSRWLockShared && 85 _PReleaseSRWLockShared ) 86 { 87 WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, 88 "Loaded Simple RW Lock"); 89 _winSupportRWLockPrimitive = true; 90 } 91 } 92 } 93 if(_winSupportRWLockPrimitive) 94 { 95 _PInitializeSRWLock(&_lock); 96 } else { 97 _critSectPtr = CriticalSectionWrapper::CreateCriticalSection(); 98 _readCondPtr = ConditionVariableWrapper::CreateConditionVariable(); 99 _writeCondPtr = ConditionVariableWrapper::CreateConditionVariable(); 100 } 101 return 0; 102} 103 104void RWLockWindows::AcquireLockExclusive() 105{ 106 if (_winSupportRWLockPrimitive) 107 { 108 _PAcquireSRWLockExclusive(&_lock); 109 } else { 110 _critSectPtr->Enter(); 111 112 if (_writerActive || _readersActive > 0) 113 { 114 ++_writersWaiting; 115 while (_writerActive || _readersActive > 0) 116 { 117 _writeCondPtr->SleepCS(*_critSectPtr); 118 } 119 --_writersWaiting; 120 } 121 _writerActive = true; 122 _critSectPtr->Leave(); 123 } 124} 125 126void RWLockWindows::ReleaseLockExclusive() 127{ 128 if(_winSupportRWLockPrimitive) 129 { 130 _PReleaseSRWLockExclusive(&_lock); 131 } else { 132 _critSectPtr->Enter(); 133 _writerActive = false; 134 if (_writersWaiting > 0) 135 { 136 _writeCondPtr->Wake(); 137 138 }else if (_readersWaiting > 0) { 139 _readCondPtr->WakeAll(); 140 } 141 _critSectPtr->Leave(); 142 } 143} 144 145void RWLockWindows::AcquireLockShared() 146{ 147 if(_winSupportRWLockPrimitive) 148 { 149 _PAcquireSRWLockShared(&_lock); 150 } else 151 { 152 _critSectPtr->Enter(); 153 if (_writerActive || _writersWaiting > 0) 154 { 155 ++_readersWaiting; 156 157 while (_writerActive || _writersWaiting > 0) 158 { 159 _readCondPtr->SleepCS(*_critSectPtr); 160 } 161 --_readersWaiting; 162 } 163 ++_readersActive; 164 _critSectPtr->Leave(); 165 } 166} 167 168void RWLockWindows::ReleaseLockShared() 169{ 170 if(_winSupportRWLockPrimitive) 171 { 172 _PReleaseSRWLockShared(&_lock); 173 } else 174 { 175 _critSectPtr->Enter(); 176 177 --_readersActive; 178 179 if (_readersActive == 0 && _writersWaiting > 0) 180 { 181 _writeCondPtr->Wake(); 182 } 183 _critSectPtr->Leave(); 184 } 185} 186} // namespace webrtc 187