• 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 #include "minddata/dataset/util/log_adapter.h"
18 
19 namespace mindspore {
20 namespace dataset {
Lock()21 void SpinLock::Lock() {
22   while (true) {
23     int expected = kUnlocked;
24     if (val_.compare_exchange_weak(expected, kLocked)) {
25       break;
26     }
27   }
28 }
29 
TryLock()30 bool SpinLock::TryLock() {
31   int expected = kUnlocked;
32   return val_.compare_exchange_strong(expected, kLocked);
33 }
34 
Unlock()35 void SpinLock::Unlock() noexcept { val_.store(kUnlocked); }
36 
LockShared()37 void RWLock::LockShared() {
38   std::unique_lock<std::mutex> lck(mtx_);
39   waiting_readers_ += 1;
40   read_cv_.wait(lck, [this]() { return (waiting_writers_ == 0 && status_ >= 0); });
41   waiting_readers_ -= 1;
42   status_ += 1;
43 }
44 
Unlock()45 void RWLock::Unlock() noexcept {
46   std::unique_lock<std::mutex> lck(mtx_);
47   if (status_ == -1) {
48     // I am the writer. By definition, no other writer nor reader.
49     status_ = 0;
50   } else if (status_ > 0) {
51     // One less reader
52     status_ -= 1;
53   }
54   // Wake up writer only if there is no reader.
55   if (waiting_writers_ > 0) {
56     if (status_ == 0) {
57       write_cv_.notify_one();
58     }
59   } else {
60     read_cv_.notify_all();
61   }
62 }
63 
Upgrade()64 void RWLock::Upgrade() {
65   std::unique_lock<std::mutex> lck(mtx_);
66   if (status_ == -1) {
67     // I am a writer already.
68     return;
69   } else if (status_ == 1) {
70     // If I am the only reader. Just change the status.
71     status_ = -1;
72     return;
73   } else {
74     // In all other cases, let of the shared lock and relock in exclusive.
75     lck.unlock();
76     this->Unlock();
77     this->LockExclusive();
78   }
79 }
80 
Downgrade()81 void RWLock::Downgrade() {
82   std::unique_lock<std::mutex> lck(mtx_);
83   if (status_ == -1) {
84     // If there are no other writers waiting, just change the status
85     if (waiting_writers_ == 0) {
86       status_ = 1;
87     } else {
88       // Otherwise just unlock and relock in shared
89       lck.unlock();
90       this->Unlock();
91       this->LockShared();
92     }
93   } else if (status_ > 0) {
94     return;
95   }
96 }
97 
SharedLock(RWLock * rw)98 SharedLock::SharedLock(RWLock *rw) : rw_(rw), ownlock_(false) {
99   rw_->LockShared();
100   ownlock_ = true;
101 }
102 
~SharedLock()103 SharedLock::~SharedLock() {
104   if (ownlock_) {
105     rw_->Unlock();
106     ownlock_ = false;
107   }
108   rw_ = nullptr;
109 }
110 
Unlock()111 void SharedLock::Unlock() {
112   rw_->Unlock();
113   ownlock_ = false;
114 }
115 
Lock()116 void SharedLock::Lock() {
117   rw_->LockShared();
118   ownlock_ = true;
119 }
120 
Upgrade()121 void SharedLock::Upgrade() { rw_->Upgrade(); }
122 
Downgrade()123 void SharedLock::Downgrade() { rw_->Downgrade(); }
124 
UniqueLock(RWLock * rw)125 UniqueLock::UniqueLock(RWLock *rw) : rw_(rw), ownlock_(false) {
126   rw_->LockExclusive();
127   ownlock_ = true;
128 }
129 
~UniqueLock()130 UniqueLock::~UniqueLock() {
131   if (ownlock_) {
132     rw_->Unlock();
133     ownlock_ = false;
134   }
135   rw_ = nullptr;
136 }
137 
Unlock()138 void UniqueLock::Unlock() {
139   rw_->Unlock();
140   ownlock_ = false;
141 }
142 
Lock()143 void UniqueLock::Lock() {
144   rw_->LockExclusive();
145   ownlock_ = true;
146 }
147 
LockGuard(SpinLock * lock)148 LockGuard::LockGuard(SpinLock *lock) : lck_(lock), own_lock_(false) {
149   lck_->Lock();
150   own_lock_ = true;
151 }
152 
~LockGuard()153 LockGuard::~LockGuard() {
154   if (own_lock_) {
155     lck_->Unlock();
156     own_lock_ = false;
157   }
158   lck_ = nullptr;
159 }
160 
Unlock()161 void LockGuard::Unlock() {
162   lck_->Unlock();
163   own_lock_ = false;
164 }
165 
Lock()166 void LockGuard::Lock() {
167   lck_->Lock();
168   own_lock_ = true;
169 }
170 }  // namespace dataset
171 }  // namespace mindspore
172