104104#include < platform/rwlock.h>
105105
106106#include < algorithm>
107+ #include < shared_mutex>
107108#include < unordered_map>
108109
109110template <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+
254301private:
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