Skip to content

Commit 364c798

Browse files
jimwwalkerdaverigby
authored andcommitted
MB-31390: [3/3] Update AtomicUnorderedMap to use read locking
For methods which don't change the map, use read locking. Change-Id: If59176585c8c9447ac83f03b4bfc6c227104f4cc Reviewed-on: http://review.couchbase.org/99883 Tested-by: Build Bot <[email protected]> Reviewed-by: Dave Rigby <[email protected]>
1 parent a38de2e commit 364c798

File tree

1 file changed

+72
-16
lines changed

1 file changed

+72
-16
lines changed

engines/ep/src/atomic_unordered_map.h

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
#include <platform/rwlock.h>
105105

106106
#include <algorithm>
107+
#include <shared_mutex>
107108
#include <unordered_map>
108109

109110
template <class Key,
@@ -129,33 +130,50 @@ class AtomicUnorderedMap {
129130
using size_type = typename base_map_type::size_type;
130131

131132
bool empty() const {
132-
std::lock_guard<cb::RWLock> guard(this->rwlock); // internally locked
133+
std::shared_lock<cb::RWLock> guard(this->rwlock); // internally locked
133134
return map.empty();
134135
}
135136

136137
size_type size() const {
137-
std::lock_guard<cb::RWLock> guard(this->rwlock); // internally locked
138+
std::shared_lock<cb::RWLock> guard(this->rwlock); // internally locked
138139
return map.size();
139140
}
140141

141142
/* Lookup */
142143

143-
/** Searches for the given key in the map.
144-
* Returns a pair consisting of:
144+
/**
145+
* Searches for the given key in the map using external shared locking
146+
* @param key Reference to the key to find
147+
* @param shared_lock reference to the shared_lock
148+
* @returns a pair consisting of:
149+
* - the found element (or a default-constructed element if not found)
150+
* - and bool denoting if the given key was found.
151+
*/
152+
std::pair<T, bool> find(const Key& key, std::shared_lock<map_type>&) {
153+
return find_UNLOCKED(key);
154+
}
155+
156+
/**
157+
* Searches for the given key in the map using external exclusive locking
158+
* @param key Reference to the key to find
159+
* @param lock_guard reference to the lock_guard
160+
* @returns a pair consisting of:
145161
* - the found element (or a default-constructed element if not found)
146162
* - and bool denoting if the given key was found.
147163
*/
148164
std::pair<T, bool> find(const Key& key, std::lock_guard<map_type>&) {
149-
// Externally locked)
150-
auto iter = map.find(key);
151-
if (iter != map.end()) {
152-
return {iter->second, true};
153-
} else {
154-
return std::make_pair(T(), false);
155-
}
165+
return find_UNLOCKED(key);
156166
}
167+
168+
/**
169+
* Searches for the given key in the map, internally locked
170+
* @param key Reference to the key to find
171+
* @returns a pair consisting of:
172+
* - the found element (or a default-constructed element if not found)
173+
* - and bool denoting if the given key was found.
174+
*/
157175
std::pair<T, bool> find(const Key& key) {
158-
std::lock_guard<map_type> guard(*this); // internally locked
176+
std::shared_lock<map_type> guard(*this); // internally locked
159177
return find(key, guard);
160178
}
161179

@@ -167,7 +185,7 @@ class AtomicUnorderedMap {
167185
*/
168186
template <class UnaryPredicate>
169187
std::pair<T, bool> find_if(UnaryPredicate p) {
170-
std::lock_guard<map_type> guard(*this); // internally locked
188+
std::shared_lock<map_type> guard(*this); // internally locked
171189
auto iter = std::find_if(map.begin(), map.end(), p);
172190
if (iter != map.end()) {
173191
return {iter->second, true};
@@ -187,20 +205,41 @@ class AtomicUnorderedMap {
187205
clear(guard);
188206
}
189207

190-
/** Applies the given function object to every element in the map.
208+
/**
209+
* Applies the given function object to every element in the map using
210+
* exclusive locking
211+
*
212+
* @param f Function object to be applied to every element in the map
213+
* @param lock_guard externally held lock
191214
*/
192215
template <class UnaryFunction>
193216
void for_each(UnaryFunction f, std::lock_guard<map_type>&) {
194-
// Externally locked
195217
std::for_each(map.begin(), map.end(), f);
196218
}
197219

220+
/**
221+
* Applies the given function object to every element in the map
222+
*
223+
* @param f Function object to be applied to every element in the map
224+
*/
198225
template <class UnaryFunction>
199226
void for_each(UnaryFunction f) {
200-
std::lock_guard<map_type> guard(*this); // internally locked
227+
std::shared_lock<map_type> guard(*this); // internally locked
201228
for_each(f, guard);
202229
}
203230

231+
/**
232+
* Applies the given function object to every element in the map using
233+
* shared_lock locking
234+
*
235+
* @param f Function object to be applied to every element in the map
236+
* @param lock_guard externally held lock
237+
*/
238+
template <class UnaryFunction>
239+
void for_each(UnaryFunction f, std::shared_lock<map_type>&) {
240+
std::for_each(map.begin(), map.end(), f);
241+
}
242+
204243
/**
205244
* Attempts to erase the given key from the map.
206245
* Returns a pair consisting of:
@@ -251,7 +290,24 @@ class AtomicUnorderedMap {
251290
rwlock.unlock();
252291
}
253292

293+
void lock_shared() {
294+
rwlock.lock_shared();
295+
}
296+
297+
void unlock_shared() {
298+
rwlock.unlock_shared();
299+
}
300+
254301
private:
302+
std::pair<T, bool> find_UNLOCKED(const Key& key) {
303+
auto iter = map.find(key);
304+
if (iter != map.end()) {
305+
return {iter->second, true};
306+
} else {
307+
return std::make_pair(T(), false);
308+
}
309+
}
310+
255311
std::unordered_map<Key, T, Hash, KeyEqual, Allocator> map;
256312
mutable cb::RWLock rwlock;
257313
};

0 commit comments

Comments
 (0)