aboutsummaryrefslogtreecommitdiff
path: root/src/system_wrappers/source/rw_lock_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/system_wrappers/source/rw_lock_win.cc')
-rw-r--r--src/system_wrappers/source/rw_lock_win.cc186
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