• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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