diff options
Diffstat (limited to 'src/system_wrappers/source/rw_lock_win.cc')
-rw-r--r-- | src/system_wrappers/source/rw_lock_win.cc | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/system_wrappers/source/rw_lock_win.cc b/src/system_wrappers/source/rw_lock_win.cc new file mode 100644 index 0000000000..82cd0ac04f --- /dev/null +++ b/src/system_wrappers/source/rw_lock_win.cc @@ -0,0 +1,186 @@ +/* + * 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 |