1 /**
2 * Copyright 2019 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "minddata/dataset/util/lock.h"
17
18 namespace mindspore {
19 namespace dataset {
Lock()20 void SpinLock::Lock() {
21 while (true) {
22 int expected = kUnlocked;
23 if (val_.compare_exchange_weak(expected, kLocked)) {
24 break;
25 }
26 }
27 }
28
TryLock()29 bool SpinLock::TryLock() {
30 int expected = kUnlocked;
31 return val_.compare_exchange_strong(expected, kLocked);
32 }
33
Unlock()34 void SpinLock::Unlock() noexcept { val_.store(kUnlocked); }
35
LockShared()36 void RWLock::LockShared() {
37 std::unique_lock<std::mutex> lck(mtx_);
38 waiting_readers_ += 1;
39 read_cv_.wait(lck, [this]() { return (waiting_writers_ == 0 && status_ >= 0); });
40 waiting_readers_ -= 1;
41 status_ += 1;
42 }
43
Unlock()44 void RWLock::Unlock() noexcept {
45 std::unique_lock<std::mutex> lck(mtx_);
46 if (status_ == -1) {
47 // I am the writer. By definition, no other writer nor reader.
48 status_ = 0;
49 } else if (status_ > 0) {
50 // One less reader
51 status_ -= 1;
52 }
53 // Wake up writer only if there is no reader.
54 if (waiting_writers_ > 0) {
55 if (status_ == 0) {
56 write_cv_.notify_one();
57 }
58 } else {
59 read_cv_.notify_all();
60 }
61 }
62
Upgrade()63 void RWLock::Upgrade() {
64 std::unique_lock<std::mutex> lck(mtx_);
65 if (status_ == -1) {
66 // I am a writer already.
67 return;
68 } else if (status_ == 1) {
69 // If I am the only reader. Just change the status.
70 status_ = -1;
71 return;
72 } else {
73 // In all other cases, let of the shared lock and relock in exclusive.
74 lck.unlock();
75 this->Unlock();
76 this->LockExclusive();
77 }
78 }
79
Downgrade()80 void RWLock::Downgrade() {
81 std::unique_lock<std::mutex> lck(mtx_);
82 if (status_ == -1) {
83 // If there are no other writers waiting, just change the status
84 if (waiting_writers_ == 0) {
85 status_ = 1;
86 } else {
87 // Otherwise just unlock and relock in shared
88 lck.unlock();
89 this->Unlock();
90 this->LockShared();
91 }
92 } else if (status_ > 0) {
93 return;
94 }
95 }
96
SharedLock(RWLock * rw)97 SharedLock::SharedLock(RWLock *rw) : rw_(rw), ownlock_(false) {
98 rw_->LockShared();
99 ownlock_ = true;
100 }
101
~SharedLock()102 SharedLock::~SharedLock() {
103 if (ownlock_) {
104 rw_->Unlock();
105 ownlock_ = false;
106 }
107 rw_ = nullptr;
108 }
109
Unlock()110 void SharedLock::Unlock() {
111 rw_->Unlock();
112 ownlock_ = false;
113 }
114
Lock()115 void SharedLock::Lock() {
116 rw_->LockShared();
117 ownlock_ = true;
118 }
119
Upgrade()120 void SharedLock::Upgrade() { rw_->Upgrade(); }
121
Downgrade()122 void SharedLock::Downgrade() { rw_->Downgrade(); }
123
UniqueLock(RWLock * rw)124 UniqueLock::UniqueLock(RWLock *rw) : rw_(rw), ownlock_(false) {
125 rw_->LockExclusive();
126 ownlock_ = true;
127 }
128
~UniqueLock()129 UniqueLock::~UniqueLock() {
130 if (ownlock_) {
131 rw_->Unlock();
132 ownlock_ = false;
133 }
134 rw_ = nullptr;
135 }
136
Unlock()137 void UniqueLock::Unlock() {
138 rw_->Unlock();
139 ownlock_ = false;
140 }
141
Lock()142 void UniqueLock::Lock() {
143 rw_->LockExclusive();
144 ownlock_ = true;
145 }
146
LockGuard(SpinLock * lock)147 LockGuard::LockGuard(SpinLock *lock) : lck_(lock), own_lock_(false) {
148 lck_->Lock();
149 own_lock_ = true;
150 }
151
~LockGuard()152 LockGuard::~LockGuard() {
153 if (own_lock_) {
154 lck_->Unlock();
155 own_lock_ = false;
156 }
157 lck_ = nullptr;
158 }
159
Unlock()160 void LockGuard::Unlock() {
161 lck_->Unlock();
162 own_lock_ = false;
163 }
164
Lock()165 void LockGuard::Lock() {
166 lck_->Lock();
167 own_lock_ = true;
168 }
169 } // namespace dataset
170 } // namespace mindspore
171