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 20 namespace webrtc { 21 bool RWLockWindows::_winSupportRWLockPrimitive = false; 22 static HMODULE library = NULL; 23 24 PInitializeSRWLock _PInitializeSRWLock; 25 PAcquireSRWLockExclusive _PAcquireSRWLockExclusive; 26 PAcquireSRWLockShared _PAcquireSRWLockShared; 27 PReleaseSRWLockShared _PReleaseSRWLockShared; 28 PReleaseSRWLockExclusive _PReleaseSRWLockExclusive; 29 30 RWLockWindows::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 41 RWLockWindows::~RWLockWindows() 42 { 43 delete _writeCondPtr; 44 delete _readCondPtr; 45 delete _critSectPtr; 46 } 47 48 int 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 104 void 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 126 void 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 145 void 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 168 void 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