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_generic.h"
12
13#include "condition_variable_wrapper.h"
14#include "critical_section_wrapper.h"
15
16namespace webrtc {
17RWLockWrapperGeneric::RWLockWrapperGeneric()
18    : _readersActive(0),
19      _writerActive(false),
20      _readersWaiting(0),
21      _writersWaiting(0)
22{
23    _critSectPtr  = CriticalSectionWrapper::CreateCriticalSection();
24    _readCondPtr  = ConditionVariableWrapper::CreateConditionVariable();
25    _writeCondPtr = ConditionVariableWrapper::CreateConditionVariable();
26}
27
28RWLockWrapperGeneric::~RWLockWrapperGeneric()
29{
30    delete _writeCondPtr;
31    delete _readCondPtr;
32    delete _critSectPtr;
33}
34
35int RWLockWrapperGeneric::Init()
36{
37    return 0;
38}
39
40void RWLockWrapperGeneric::AcquireLockExclusive()
41{
42    _critSectPtr->Enter();
43
44    if (_writerActive || _readersActive > 0)
45    {
46        ++_writersWaiting;
47
48        while (_writerActive || _readersActive > 0)
49        {
50            _writeCondPtr->SleepCS(*_critSectPtr);
51        }
52
53        --_writersWaiting;
54    }
55    _writerActive = true;
56    _critSectPtr->Leave();
57}
58
59void RWLockWrapperGeneric::ReleaseLockExclusive()
60{
61    _critSectPtr->Enter();
62
63    _writerActive = false;
64
65    if (_writersWaiting > 0)
66    {
67        _writeCondPtr->Wake();
68
69    }else if (_readersWaiting > 0)
70    {
71        _readCondPtr->WakeAll();
72    }
73    _critSectPtr->Leave();
74}
75
76void RWLockWrapperGeneric::AcquireLockShared()
77{
78    _critSectPtr->Enter();
79
80    if (_writerActive || _writersWaiting > 0)
81    {
82        ++_readersWaiting;
83
84        while (_writerActive || _writersWaiting > 0)
85        {
86            _readCondPtr->SleepCS(*_critSectPtr);
87        }
88        --_readersWaiting;
89    }
90    ++_readersActive;
91    _critSectPtr->Leave();
92}
93
94void RWLockWrapperGeneric::ReleaseLockShared()
95{
96    _critSectPtr->Enter();
97
98    --_readersActive;
99
100    if (_readersActive == 0 && _writersWaiting > 0)
101    {
102        _writeCondPtr->Wake();
103    }
104    _critSectPtr->Leave();
105}
106} // namespace webrtc
107