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
RWLockWindows()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
~RWLockWindows()41 RWLockWindows::~RWLockWindows()
42 {
43 delete _writeCondPtr;
44 delete _readCondPtr;
45 delete _critSectPtr;
46 }
47
Init()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
AcquireLockExclusive()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
ReleaseLockExclusive()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
AcquireLockShared()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
ReleaseLockShared()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