1a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin/*
2a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *
4a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  Use of this source code is governed by a BSD-style license
5a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  that can be found in the LICENSE file in the root of the source
6a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  tree. An additional intellectual property rights grant can be found
7a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  in the file PATENTS.  All contributing project authors may
8a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  be found in the AUTHORS file in the root of the source tree.
9a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin */
10a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
11a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "rw_lock_win.h"
12a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
13a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "critical_section_wrapper.h"
14a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "condition_variable_wrapper.h"
15a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "trace.h"
16a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
17a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// TODO (hellner) why not just use the rw_lock_generic.cc solution if
18a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin//                           native is not supported? Unnecessary redundancy!
19a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
20a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinnamespace webrtc {
21a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool RWLockWindows::_winSupportRWLockPrimitive = false;
22a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinstatic HMODULE library = NULL;
23a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
24a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPInitializeSRWLock       _PInitializeSRWLock;
25a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPAcquireSRWLockExclusive _PAcquireSRWLockExclusive;
26a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPAcquireSRWLockShared    _PAcquireSRWLockShared;
27a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPReleaseSRWLockShared    _PReleaseSRWLockShared;
28a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinPReleaseSRWLockExclusive _PReleaseSRWLockExclusive;
29a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
30a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinRWLockWindows::RWLockWindows()
31a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    : _critSectPtr(NULL),
32a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _readCondPtr(NULL),
33a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _writeCondPtr(NULL),
34a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _readersActive(0),
35a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _writerActive(false),
36a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _readersWaiting(0),
37a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _writersWaiting(0)
38a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
39a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
40a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
41a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinRWLockWindows::~RWLockWindows()
42a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
43a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    delete _writeCondPtr;
44a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    delete _readCondPtr;
45a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    delete _critSectPtr;
46a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
47a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
48a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinint RWLockWindows::Init()
49a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
50a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(!library)
51a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
52a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Use native implementation if supported (i.e Vista+)
53a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        library = LoadLibrary(TEXT("Kernel32.dll"));
54a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if(library)
55a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
56a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
57a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                         "Loaded Kernel.dll");
58a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
59a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _PInitializeSRWLock =
60a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                (PInitializeSRWLock)GetProcAddress(
61a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                    library,
62a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                    "InitializeSRWLock");
63a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
64a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _PAcquireSRWLockExclusive =
65a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin               (PAcquireSRWLockExclusive)GetProcAddress(
66a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                   library,
67a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                   "AcquireSRWLockExclusive");
68a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _PReleaseSRWLockExclusive =
69a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                (PReleaseSRWLockExclusive)GetProcAddress(
70a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                    library,
71a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                    "ReleaseSRWLockExclusive");
72a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _PAcquireSRWLockShared =
73a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                (PAcquireSRWLockShared)GetProcAddress(
74a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                    library,
75a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                    "AcquireSRWLockShared");
76a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _PReleaseSRWLockShared =
77a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                (PReleaseSRWLockShared)GetProcAddress(
78a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                    library,
79a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                    "ReleaseSRWLockShared");
80a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
81a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            if( _PInitializeSRWLock &&
82a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                _PAcquireSRWLockExclusive &&
83a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                _PReleaseSRWLockExclusive &&
84a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                _PAcquireSRWLockShared &&
85a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                _PReleaseSRWLockShared )
86a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            {
87a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
88a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                            "Loaded Simple RW Lock");
89a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                _winSupportRWLockPrimitive = true;
90a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            }
91a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
92a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
93a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(_winSupportRWLockPrimitive)
94a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
95a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _PInitializeSRWLock(&_lock);
96a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    } else {
97a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr  = CriticalSectionWrapper::CreateCriticalSection();
98a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _readCondPtr  = ConditionVariableWrapper::CreateConditionVariable();
99a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _writeCondPtr = ConditionVariableWrapper::CreateConditionVariable();
100a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
101a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return 0;
102a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
103a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
104a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid RWLockWindows::AcquireLockExclusive()
105a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
106a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_winSupportRWLockPrimitive)
107a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
108a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _PAcquireSRWLockExclusive(&_lock);
109a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    } else {
110a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr->Enter();
111a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
112a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (_writerActive || _readersActive > 0)
113a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
114a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            ++_writersWaiting;
115a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            while (_writerActive || _readersActive > 0)
116a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            {
117a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                _writeCondPtr->SleepCS(*_critSectPtr);
118a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            }
119a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            --_writersWaiting;
120a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
121a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _writerActive = true;
122a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr->Leave();
123a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
124a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
125a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
126a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid RWLockWindows::ReleaseLockExclusive()
127a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
128a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(_winSupportRWLockPrimitive)
129a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
130a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _PReleaseSRWLockExclusive(&_lock);
131a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    } else {
132a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr->Enter();
133a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _writerActive = false;
134a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (_writersWaiting > 0)
135a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
136a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _writeCondPtr->Wake();
137a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
138a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }else if (_readersWaiting > 0) {
139a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _readCondPtr->WakeAll();
140a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
141a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr->Leave();
142a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
143a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
144a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
145a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid RWLockWindows::AcquireLockShared()
146a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
147a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(_winSupportRWLockPrimitive)
148a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
149a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _PAcquireSRWLockShared(&_lock);
150a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    } else
151a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
152a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr->Enter();
153a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (_writerActive || _writersWaiting > 0)
154a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
155a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            ++_readersWaiting;
156a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
157a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            while (_writerActive || _writersWaiting > 0)
158a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            {
159a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                _readCondPtr->SleepCS(*_critSectPtr);
160a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            }
161a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            --_readersWaiting;
162a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
163a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        ++_readersActive;
164a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr->Leave();
165a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
166a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
167a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
168a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid RWLockWindows::ReleaseLockShared()
169a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
170a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(_winSupportRWLockPrimitive)
171a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
172a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _PReleaseSRWLockShared(&_lock);
173a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    } else
174a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
175a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr->Enter();
176a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
177a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        --_readersActive;
178a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
179a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (_readersActive == 0 && _writersWaiting > 0)
180a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
181a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _writeCondPtr->Wake();
182a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
183a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critSectPtr->Leave();
184a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
185a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
186a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} // namespace webrtc
187