| /* |
| * Copyright (c) 2011 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 "rw_lock_win.h" |
| |
| #include "critical_section_wrapper.h" |
| #include "condition_variable_wrapper.h" |
| #include "trace.h" |
| |
| // TODO (hellner) why not just use the rw_lock_generic.cc solution if |
| // native is not supported? Unnecessary redundancy! |
| |
| namespace webrtc { |
| bool RWLockWindows::_winSupportRWLockPrimitive = false; |
| static HMODULE library = NULL; |
| |
| PInitializeSRWLock _PInitializeSRWLock; |
| PAcquireSRWLockExclusive _PAcquireSRWLockExclusive; |
| PAcquireSRWLockShared _PAcquireSRWLockShared; |
| PReleaseSRWLockShared _PReleaseSRWLockShared; |
| PReleaseSRWLockExclusive _PReleaseSRWLockExclusive; |
| |
| RWLockWindows::RWLockWindows() |
| : _critSectPtr(NULL), |
| _readCondPtr(NULL), |
| _writeCondPtr(NULL), |
| _readersActive(0), |
| _writerActive(false), |
| _readersWaiting(0), |
| _writersWaiting(0) |
| { |
| } |
| |
| RWLockWindows::~RWLockWindows() |
| { |
| delete _writeCondPtr; |
| delete _readCondPtr; |
| delete _critSectPtr; |
| } |
| |
| int RWLockWindows::Init() |
| { |
| 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"); |
| |
| _PInitializeSRWLock = |
| (PInitializeSRWLock)GetProcAddress( |
| library, |
| "InitializeSRWLock"); |
| |
| _PAcquireSRWLockExclusive = |
| (PAcquireSRWLockExclusive)GetProcAddress( |
| library, |
| "AcquireSRWLockExclusive"); |
| _PReleaseSRWLockExclusive = |
| (PReleaseSRWLockExclusive)GetProcAddress( |
| library, |
| "ReleaseSRWLockExclusive"); |
| _PAcquireSRWLockShared = |
| (PAcquireSRWLockShared)GetProcAddress( |
| library, |
| "AcquireSRWLockShared"); |
| _PReleaseSRWLockShared = |
| (PReleaseSRWLockShared)GetProcAddress( |
| library, |
| "ReleaseSRWLockShared"); |
| |
| if( _PInitializeSRWLock && |
| _PAcquireSRWLockExclusive && |
| _PReleaseSRWLockExclusive && |
| _PAcquireSRWLockShared && |
| _PReleaseSRWLockShared ) |
| { |
| WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, |
| "Loaded Simple RW Lock"); |
| _winSupportRWLockPrimitive = true; |
| } |
| } |
| } |
| if(_winSupportRWLockPrimitive) |
| { |
| _PInitializeSRWLock(&_lock); |
| } else { |
| _critSectPtr = CriticalSectionWrapper::CreateCriticalSection(); |
| _readCondPtr = ConditionVariableWrapper::CreateConditionVariable(); |
| _writeCondPtr = ConditionVariableWrapper::CreateConditionVariable(); |
| } |
| return 0; |
| } |
| |
| void RWLockWindows::AcquireLockExclusive() |
| { |
| if (_winSupportRWLockPrimitive) |
| { |
| _PAcquireSRWLockExclusive(&_lock); |
| } else { |
| _critSectPtr->Enter(); |
| |
| if (_writerActive || _readersActive > 0) |
| { |
| ++_writersWaiting; |
| while (_writerActive || _readersActive > 0) |
| { |
| _writeCondPtr->SleepCS(*_critSectPtr); |
| } |
| --_writersWaiting; |
| } |
| _writerActive = true; |
| _critSectPtr->Leave(); |
| } |
| } |
| |
| void RWLockWindows::ReleaseLockExclusive() |
| { |
| if(_winSupportRWLockPrimitive) |
| { |
| _PReleaseSRWLockExclusive(&_lock); |
| } else { |
| _critSectPtr->Enter(); |
| _writerActive = false; |
| if (_writersWaiting > 0) |
| { |
| _writeCondPtr->Wake(); |
| |
| }else if (_readersWaiting > 0) { |
| _readCondPtr->WakeAll(); |
| } |
| _critSectPtr->Leave(); |
| } |
| } |
| |
| void RWLockWindows::AcquireLockShared() |
| { |
| if(_winSupportRWLockPrimitive) |
| { |
| _PAcquireSRWLockShared(&_lock); |
| } else |
| { |
| _critSectPtr->Enter(); |
| if (_writerActive || _writersWaiting > 0) |
| { |
| ++_readersWaiting; |
| |
| while (_writerActive || _writersWaiting > 0) |
| { |
| _readCondPtr->SleepCS(*_critSectPtr); |
| } |
| --_readersWaiting; |
| } |
| ++_readersActive; |
| _critSectPtr->Leave(); |
| } |
| } |
| |
| void RWLockWindows::ReleaseLockShared() |
| { |
| if(_winSupportRWLockPrimitive) |
| { |
| _PReleaseSRWLockShared(&_lock); |
| } else |
| { |
| _critSectPtr->Enter(); |
| |
| --_readersActive; |
| |
| if (_readersActive == 0 && _writersWaiting > 0) |
| { |
| _writeCondPtr->Wake(); |
| } |
| _critSectPtr->Leave(); |
| } |
| } |
| } // namespace webrtc |