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 
16 namespace webrtc {
RWLockWrapperGeneric()17 RWLockWrapperGeneric::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 
~RWLockWrapperGeneric()28 RWLockWrapperGeneric::~RWLockWrapperGeneric()
29 {
30     delete _writeCondPtr;
31     delete _readCondPtr;
32     delete _critSectPtr;
33 }
34 
Init()35 int RWLockWrapperGeneric::Init()
36 {
37     return 0;
38 }
39 
AcquireLockExclusive()40 void 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 
ReleaseLockExclusive()59 void 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 
AcquireLockShared()76 void 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 
ReleaseLockShared()94 void 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