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 "webrtc/system_wrappers/source/rw_lock_generic.h"
12
13#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
14#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
15
16namespace webrtc {
17
18RWLockGeneric::RWLockGeneric()
19    : readers_active_(0),
20      writer_active_(false),
21      readers_waiting_(0),
22      writers_waiting_(0) {
23  critical_section_ = CriticalSectionWrapper::CreateCriticalSection();
24  read_condition_ = ConditionVariableWrapper::CreateConditionVariable();
25  write_condition_ = ConditionVariableWrapper::CreateConditionVariable();
26}
27
28RWLockGeneric::~RWLockGeneric() {
29  delete write_condition_;
30  delete read_condition_;
31  delete critical_section_;
32}
33
34void RWLockGeneric::AcquireLockExclusive() {
35  CriticalSectionScoped cs(critical_section_);
36  if (writer_active_ || readers_active_ > 0) {
37    ++writers_waiting_;
38    while (writer_active_ || readers_active_ > 0) {
39      write_condition_->SleepCS(*critical_section_);
40    }
41    --writers_waiting_;
42  }
43  writer_active_ = true;
44}
45
46void RWLockGeneric::ReleaseLockExclusive() {
47  CriticalSectionScoped cs(critical_section_);
48  writer_active_ = false;
49  if (writers_waiting_ > 0) {
50    write_condition_->Wake();
51  } else if (readers_waiting_ > 0) {
52    read_condition_->WakeAll();
53  }
54}
55
56void RWLockGeneric::AcquireLockShared() {
57  CriticalSectionScoped cs(critical_section_);
58  if (writer_active_ || writers_waiting_ > 0) {
59    ++readers_waiting_;
60
61    while (writer_active_ || writers_waiting_ > 0) {
62      read_condition_->SleepCS(*critical_section_);
63    }
64    --readers_waiting_;
65  }
66  ++readers_active_;
67}
68
69void RWLockGeneric::ReleaseLockShared() {
70  CriticalSectionScoped cs(critical_section_);
71  --readers_active_;
72  if (readers_active_ == 0 && writers_waiting_ > 0) {
73    write_condition_->Wake();
74  }
75}
76
77}  // namespace webrtc
78