ATLAS Offline Software
ConcurrentStrToValMap.icc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration.
3  */
4 /**
5  * @file CxxUtils/ConcurrentStrToValMap.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Jul, 2023
8  * @brief Hash map from strings to arbitrary objects allowing
9  * concurrent, lockless reads.
10  */
11 
12 
13 namespace CxxUtils {
14 
15 
16 #define T_CONCURRENTSTRTOVALMAP template <class VALUE, \
17  template <class> class UPDATER> \
18  ATH_REQUIRES (detail::IsUpdater<UPDATER>)
19 
20 #define CONCURRENTSTRTOVALMAP ConcurrentStrToValMap<VALUE, UPDATER>
21 
22 
23 /**
24  * @brief Constructor.
25  * @param updater Object used to manage memory
26  * (see comments at the start of the class).
27  * @param capacity The initial table capacity.
28  * (Will be rounded up to a power of two.)
29  * @param ctx Execution context.
30  */
31 T_CONCURRENTSTRTOVALMAP
32 CONCURRENTSTRTOVALMAP::ConcurrentStrToValMap (Updater_t&& updater,
33  size_type capacity /*= 64*/,
34  const Context_t& ctx
35  /* = Updater_t::defaultContext()*/)
36  : m_impl (std::move (updater),
37  capacity,
38  Hasher(),
39  Matcher(),
40  ctx)
41 {
42 }
43 
44 
45 /**
46  * @brief Constructor from another map.
47  * @param updater Object used to manage memory
48  * (see comments at the start of the class).
49  * @param capacity The initial table capacity of the new table.
50  * (Will be rounded up to a power of two.)
51  * @param ctx Execution context.
52  *
53  * (Not really a copy constructor since we need to pass @c updater.)
54  */
55 T_CONCURRENTSTRTOVALMAP
56 CONCURRENTSTRTOVALMAP::ConcurrentStrToValMap (const ConcurrentStrToValMap& other,
57  Updater_t&& updater,
58  size_type capacity /*= 64*/,
59  const Context_t& ctx
60  /*= Updater_t::defaultContext()*/)
61  : m_impl (std::move (updater),
62  capacity,
63  Hasher(),
64  Matcher(),
65  ctx)
66 {
67  // not using reference, because our iterator doesn't return a reference
68  for (const auto p : other) {
69  this->put (std::make_unique<key_type> (p.first),
70  std::make_unique<mapped_type> (p.second),
71  ctx);
72  }
73 }
74 
75 
76 /**
77  * @brief Constructor from a range.
78  * @param f Start iterator for the range.
79  * @param l End iterator for the range.
80  * @param updater Object used to manage memory
81  * (see comments at the start of the class).
82  * @param capacity The initial table capacity of the new table.
83  * (Will be rounded up to a power of two.)
84  * @param ctx Execution context.
85  *
86  * Constructor from a range of pairs.
87  */
88 T_CONCURRENTSTRTOVALMAP
89 template <class InputIterator>
90 CONCURRENTSTRTOVALMAP::ConcurrentStrToValMap (InputIterator f,
91  InputIterator l,
92  Updater_t&& updater,
93  size_t capacity /*= 64*/,
94  const Context_t& ctx
95  /*= Updater_t::defaultContext()*/)
96  : m_impl (std::move (updater),
97  capacity,
98  Hasher(),
99  Matcher(),
100  ctx)
101 {
102  if constexpr (std::is_rvalue_reference_v<typename InputIterator::reference>)
103  {
104  for (; f != l; ++f) {
105  emplace (std::move (f->first), std::move (f->second), ctx);
106  }
107  }
108  else {
109  for (; f != l; ++f) {
110  emplace (f->first, f->second, ctx);
111  }
112  }
113 }
114 
115 
116 /**
117  * @brief Destructor.
118  */
119 T_CONCURRENTSTRTOVALMAP
120 CONCURRENTSTRTOVALMAP::~ConcurrentStrToValMap()
121 {
122  // Need to delete the strings and values that we've stored.
123  auto [begin, end] = m_impl.range();
124  while (begin != end) {
125  if (begin.key() != Impl_t::nullval) {
126  delete keyAsString (begin.key());
127  delete mappedAsMapped (begin.value());
128  }
129  begin.next();
130  }
131 }
132 
133 
134 /**
135  * @brief Return the number of items currently in the map.
136  */
137 T_CONCURRENTSTRTOVALMAP
138 inline
139 auto CONCURRENTSTRTOVALMAP::size() const -> size_type
140 {
141  return m_impl.size();
142 }
143 
144 
145 /**
146  * @brief Test if the map is currently empty.
147  */
148 T_CONCURRENTSTRTOVALMAP
149 inline
150 bool CONCURRENTSTRTOVALMAP::empty() const
151 {
152  return !m_impl.size();
153 }
154 
155 
156 /**
157  * @brief Return the current size (capacity) of the hash table.
158  */
159 T_CONCURRENTSTRTOVALMAP
160 inline
161 auto CONCURRENTSTRTOVALMAP::capacity() const -> size_t
162 {
163  return m_impl.capacity();
164 }
165 
166 
167 /**
168  * @brief Constructor.
169  * @param it Iterator of the underlying table.
170  */
171 T_CONCURRENTSTRTOVALMAP
172 inline
173 CONCURRENTSTRTOVALMAP::const_iterator::const_iterator (typename Impl_t::const_iterator it)
174  : m_impl (it)
175 {
176 }
177 
178 
179 /**
180  * @brief Conversion from non-const iterator (for interoperability).
181  * @param other The other iterator.
182  */
183 T_CONCURRENTSTRTOVALMAP
184 inline
185 CONCURRENTSTRTOVALMAP::const_iterator::const_iterator (const iterator& other)
186  : m_impl (other.m_impl)
187 {
188 }
189 
190 
191 /**
192  * @brief Test if this iterator is valid.
193  *
194  * This should be the same as testing for != end().
195  */
196 T_CONCURRENTSTRTOVALMAP
197 inline
198 auto CONCURRENTSTRTOVALMAP::const_iterator::valid() const -> bool
199 {
200  return m_impl.valid();
201 }
202 
203 
204 /**
205  * @brief iterator_facade requirement: Increment the iterator.
206  */
207 T_CONCURRENTSTRTOVALMAP
208 inline
209 auto CONCURRENTSTRTOVALMAP::const_iterator::increment() -> void
210 {
211  m_impl.next();
212 }
213 
214 
215 /**
216  * @brief iterator_facade requirement: Decrement the iterator.
217  */
218 T_CONCURRENTSTRTOVALMAP
219 inline
220 auto CONCURRENTSTRTOVALMAP::const_iterator::decrement() -> void
221 {
222  m_impl.prev();
223 }
224 
225 
226 /**
227  * @brief iterator_facade requirement: Dereference the iterator.
228  */
229 T_CONCURRENTSTRTOVALMAP
230 inline
231 auto CONCURRENTSTRTOVALMAP::const_iterator::dereference() const
232  -> const const_iterator_value
233 {
234  return const_iterator_value (*keyAsString (m_impl.key()),
235  *mappedAsMapped (m_impl.value()));
236 }
237 
238 
239 /**
240  * @brief iterator_facade requirement: Equality test.
241  */
242 T_CONCURRENTSTRTOVALMAP
243 inline
244 auto CONCURRENTSTRTOVALMAP::const_iterator::equal (const const_iterator& other) const
245  -> bool
246 {
247  return !(m_impl != other.m_impl);
248 }
249 
250 
251 /**
252  * @brief iterator_facade requirement: Equality test. (Interoperability.)
253  */
254 T_CONCURRENTSTRTOVALMAP
255 inline
256 auto CONCURRENTSTRTOVALMAP::const_iterator::equal (const iterator& other) const
257  -> bool
258 {
259  return !(m_impl != other.m_impl);
260 }
261 
262 
263 /**
264  * @brief Constructor.
265  * @param it Iterator of the underlying table.
266  */
267 T_CONCURRENTSTRTOVALMAP
268 inline
269 CONCURRENTSTRTOVALMAP::iterator::iterator (typename Impl_t::const_iterator it)
270  : m_impl (it)
271 {
272 }
273 
274 
275 /**
276  * @brief Test if this iterator is valid.
277  *
278  * This should be the same as testing for != end().
279  */
280 T_CONCURRENTSTRTOVALMAP
281 inline
282 auto CONCURRENTSTRTOVALMAP::iterator::valid() const -> bool
283 {
284  return m_impl.valid();
285 }
286 
287 
288 /**
289  * @brief iterator_facade requirement: Increment the iterator.
290  */
291 T_CONCURRENTSTRTOVALMAP
292 inline
293 auto CONCURRENTSTRTOVALMAP::iterator::increment() -> void
294 {
295  m_impl.next();
296 }
297 
298 
299 /**
300  * @brief iterator_facade requirement: Decrement the iterator.
301  */
302 T_CONCURRENTSTRTOVALMAP
303 inline
304 auto CONCURRENTSTRTOVALMAP::iterator::decrement() -> void
305 {
306  m_impl.prev();
307 }
308 
309 
310 /**
311  * @brief iterator_facade requirement: Dereference the iterator.
312  */
313 T_CONCURRENTSTRTOVALMAP
314 inline
315 auto CONCURRENTSTRTOVALMAP::iterator::dereference() const
316  -> const iterator_value
317 {
318  return iterator_value (*keyAsString (m_impl.key()),
319  *mappedAsMapped (m_impl.value()));
320 }
321 
322 
323 /**
324  * @brief iterator_facade requirement: Equality test.
325  */
326 T_CONCURRENTSTRTOVALMAP
327 inline
328 auto CONCURRENTSTRTOVALMAP::iterator::equal (const iterator& other) const
329  -> bool
330 {
331  return !(m_impl != other.m_impl);
332 }
333 
334 
335 /**
336  * @brief iterator_facade requirement: Equality test. (Interoperability.)
337  */
338 T_CONCURRENTSTRTOVALMAP
339 inline
340 auto CONCURRENTSTRTOVALMAP::iterator::equal (const const_iterator& other) const
341  -> bool
342 {
343  return !(m_impl != other.m_impl);
344 }
345 
346 
347 /**
348  * @brief Return an iterator range covering the entire map.
349  */
350 T_CONCURRENTSTRTOVALMAP
351 auto CONCURRENTSTRTOVALMAP::range() const -> const_iterator_range
352 {
353  auto [begin, end] = m_impl.range();
354  return const_iterator_range (begin, end);
355 }
356 
357 
358 /**
359  * @brief Return an iterator range covering the entire map.
360  *
361  * The mapped objects must themselves be thread-safe in order to make
362  * any changes to them through the returned iterators.
363  */
364 T_CONCURRENTSTRTOVALMAP
365 auto CONCURRENTSTRTOVALMAP::range() -> iterator_range
366 {
367  auto [begin, end] = m_impl.range();
368  return iterator_range (begin, end);
369 }
370 
371 
372 /**
373  * @brief Iterator at the start of the map.
374  */
375 T_CONCURRENTSTRTOVALMAP
376 inline
377 auto CONCURRENTSTRTOVALMAP::begin() const -> const_iterator
378 {
379  return const_iterator (m_impl.begin());
380 }
381 
382 
383 /**
384  * @brief Iterator at the end of the map.
385  */
386 T_CONCURRENTSTRTOVALMAP
387 inline
388 auto CONCURRENTSTRTOVALMAP::end() const -> const_iterator
389 {
390  return const_iterator (m_impl.end());
391 }
392 
393 
394 /**
395  * @brief Iterator at the start of the map.
396  *
397  * The mapped objects must themselves be thread-safe in order to make
398  * any changes to them through the returned iterators.
399  */
400 T_CONCURRENTSTRTOVALMAP
401 inline
402 auto CONCURRENTSTRTOVALMAP::begin() -> iterator
403 {
404  return iterator (m_impl.begin());
405 }
406 
407 
408 /**
409  * @brief Iterator at the end of the map.
410  *
411  * The mapped objects must themselves be thread-safe in order to make
412  * any changes to them through the returned iterators.
413  */
414 T_CONCURRENTSTRTOVALMAP
415 inline
416 auto CONCURRENTSTRTOVALMAP::end() -> iterator
417 {
418  return iterator (m_impl.end());
419 }
420 
421 
422 /**
423  * @brief Iterator at the start of the map.
424  */
425 T_CONCURRENTSTRTOVALMAP
426 inline
427 auto CONCURRENTSTRTOVALMAP::cbegin() const -> const_iterator
428 {
429  return begin();
430 }
431 
432 
433 /**
434  * @brief Iterator at the end of the map.
435  */
436 T_CONCURRENTSTRTOVALMAP
437 inline
438 auto CONCURRENTSTRTOVALMAP::cend() const -> const_iterator
439 {
440  return end();
441 }
442 
443 
444 /**
445  * @brief Test if a key is in the container.
446  * @param key The key to test.
447  */
448 T_CONCURRENTSTRTOVALMAP
449 inline
450 bool CONCURRENTSTRTOVALMAP::contains (const key_type& key) const
451 {
452  return get(key).valid();
453 }
454 
455 
456 /**
457  * @brief Return the number of times a given key is in the container.
458  * @param key The key to test.
459  *
460  * Returns either 0 or 1, depending on whether or not the key is in the map.
461  */
462 T_CONCURRENTSTRTOVALMAP
463 inline
464 auto CONCURRENTSTRTOVALMAP::count (const key_type& key) const -> size_type
465 {
466  return contains (key) ? 1 : 0;
467 }
468 
469 
470 /**
471  * @brief Look up an element in the map.
472  * @param key The element to find.
473  *
474  * Returns either an iterator referencing the found element or end().
475  */
476 T_CONCURRENTSTRTOVALMAP
477 inline
478 auto CONCURRENTSTRTOVALMAP::find (const key_type& key) const -> const_iterator
479 {
480  return const_iterator (this->get (key));
481 }
482 
483 
484 /**
485  * @brief Look up an element in the map.
486  * @param key The element to find.
487  *
488  * Returns either an iterator referencing the found element or end().
489  *
490  * The mapped object must itself be thread-safe in order to make
491  * any changes to it through the returned iterator.
492  */
493 T_CONCURRENTSTRTOVALMAP
494 inline
495 auto CONCURRENTSTRTOVALMAP::find (const key_type& key) -> iterator
496 {
497  return iterator (this->get (key));
498 }
499 
500 
501 /**
502  * @brief Look up an element in the map.
503  * @param key The element to find.
504  *
505  * Returns the value associated with the key.
506  * Throws @c std::out_of_range if the key does not exist in the map.
507  */
508 T_CONCURRENTSTRTOVALMAP
509 auto CONCURRENTSTRTOVALMAP::at (const key_type& key) const -> const mapped_type&
510 {
511  typename Impl_t::const_iterator it = this->get (key);
512  if (!it.valid()) {
513  throw std::out_of_range ("ConcurrentToValMap::at");
514  }
515  return *mappedAsMapped (it.value());
516 }
517 
518 
519 /**
520  * @brief Look up an element in the map.
521  * @param key The element to find.
522  *
523  * Returns the value associated with the key.
524  * Throws @c std::out_of_range if the key does not exist in the map.
525  *
526  * This returns a non-const reference to the mapped object.
527  * The mapped object must be thread-safe itself in order to safely
528  * make any changes to it.
529  */
530 T_CONCURRENTSTRTOVALMAP
531 auto CONCURRENTSTRTOVALMAP::at (const key_type& key) -> mapped_type&
532 {
533  typename Impl_t::const_iterator it = this->get (key);
534  if (!it.valid()) {
535  throw std::out_of_range ("ConcurrentToValMap::at");
536  }
537  return *mappedAsMapped (it.value());
538 }
539 
540 
541 /**
542  * @brief Return a range of iterators with entries matching @c key.
543  * @param key The element to find.
544  *
545  * As keys are unique in this container, this is either a single-element
546  * range, or both iterators are equal to end().
547  */
548 T_CONCURRENTSTRTOVALMAP
549 auto CONCURRENTSTRTOVALMAP::equal_range (const key_type& key) const
550  -> std::pair<const_iterator, const_iterator>
551 {
552  const_iterator i1 = find (key);
553  const_iterator i2 = i1;
554  if (i2.valid()) {
555  ++i2;
556  }
557  return std::make_pair (i1, i2);
558 }
559 
560 
561 /**
562  * @brief Return a range of iterators with entries matching @c key.
563  * @param key The element to find.
564  *
565  * As keys are unique in this container, this is either a single-element
566  * range, or both iterators are equal to end().
567  *
568  * The mapped objects must themselves be thread-safe in order to make
569  * any changes to them through the returned iterators.
570  */
571 T_CONCURRENTSTRTOVALMAP
572 auto CONCURRENTSTRTOVALMAP::equal_range (const key_type& key)
573  -> std::pair<iterator, iterator>
574 {
575  iterator i1 = find (key);
576  iterator i2 = i1;
577  if (i2.valid()) {
578  ++i2;
579  }
580  return std::make_pair (i1, i2);
581 }
582 
583 
584 /**
585  * @brief Add an element to the map.
586  * @param key The key of the new item to add.
587  * @param val The value of the new item to add.
588  * @param ctx Execution context.
589  *
590  * This will not overwrite an existing entry.
591  * The first element in the returned pair is an iterator referencing
592  * the added item. The second is a flag that is true if a new element
593  * was added.
594  */
595 T_CONCURRENTSTRTOVALMAP
596 inline
597 auto CONCURRENTSTRTOVALMAP::emplace (const key_type& key,
598  const mapped_type& val,
599  const Context_t& ctx
600  /*= Updater_t::defaultContext()*/)
601  -> std::pair<const_iterator, bool>
602 {
603  return put (std::make_unique<key_type> (key),
604  std::make_unique<mapped_type> (val),
605  ctx);
606 }
607 
608 
609 /**
610  * @brief Add an element to the map.
611  * @param key The key of the new item to add.
612  * @param val The value of the new item to add.
613  * @param ctx Execution context.
614  *
615  * This will not overwrite an existing entry.
616  * The first element in the returned pair is an iterator referencing
617  * the added item. The second is a flag that is true if a new element
618  * was added.
619  */
620 T_CONCURRENTSTRTOVALMAP
621 inline
622 auto CONCURRENTSTRTOVALMAP::emplace (key_type&& key,
623  const mapped_type& val,
624  const Context_t& ctx
625  /*= Updater_t::defaultContext()*/)
626  -> std::pair<const_iterator, bool>
627 {
628  return put (std::make_unique<key_type> (std::move (key)),
629  std::make_unique<mapped_type> (val),
630  ctx);
631 }
632 
633 
634 /**
635  * @brief Add an element to the map.
636  * @param key The key of the new item to add.
637  * @param val The value of the new item to add.
638  * @param ctx Execution context.
639  *
640  * This will not overwrite an existing entry.
641  * The first element in the returned pair is an iterator referencing
642  * the added item. The second is a flag that is true if a new element
643  * was added.
644  */
645 T_CONCURRENTSTRTOVALMAP
646 inline
647 auto CONCURRENTSTRTOVALMAP::emplace (const key_type& key,
648  mapped_type&& val,
649  const Context_t& ctx
650  /*= Updater_t::defaultContext()*/)
651  -> std::pair<const_iterator, bool>
652 {
653  return put (std::make_unique<key_type> (key),
654  std::make_unique<mapped_type> (std::move (val)),
655  ctx);
656 }
657 
658 
659 /**
660  * @brief Add an element to the map.
661  * @param key The key of the new item to add.
662  * @param val The value of the new item to add.
663  * @param ctx Execution context.
664  *
665  * This will not overwrite an existing entry.
666  * The first element in the returned pair is an iterator referencing
667  * the added item. The second is a flag that is true if a new element
668  * was added.
669  */
670 T_CONCURRENTSTRTOVALMAP
671 inline
672 auto CONCURRENTSTRTOVALMAP::emplace (key_type&& key,
673  mapped_type&& val,
674  const Context_t& ctx
675  /*= Updater_t::defaultContext()*/)
676  -> std::pair<const_iterator, bool>
677 {
678  return put (std::make_unique<key_type> (std::move (key)),
679  std::make_unique<mapped_type> (std::move (val)),
680  ctx);
681 }
682 
683 
684 /**
685  * @brief Add an element to the map.
686  * @param key The key of the new item to add.
687  * @param val The value of the new item to add.
688  * @param ctx Execution context.
689  *
690  * This will not overwrite an existing entry.
691  * The first element in the returned pair is an iterator referencing
692  * the added item. The second is a flag that is true if a new element
693  * was added.
694  */
695 T_CONCURRENTSTRTOVALMAP
696 inline
697 auto CONCURRENTSTRTOVALMAP::emplace (const key_type& key,
698  std::unique_ptr<mapped_type> val,
699  const Context_t& ctx
700  /*= Updater_t::defaultContext()*/)
701  -> std::pair<const_iterator, bool>
702 {
703  return put (std::make_unique<key_type> (key),
704  std::move (val),
705  ctx);
706 }
707 
708 
709 /**
710  * @brief Add an element to the map.
711  * @param key The key of the new item to add.
712  * @param val The value of the new item to add.
713  * @param ctx Execution context.
714  *
715  * This will not overwrite an existing entry.
716  * The first element in the returned pair is an iterator referencing
717  * the added item. The second is a flag that is true if a new element
718  * was added.
719  */
720 T_CONCURRENTSTRTOVALMAP
721 inline
722 auto CONCURRENTSTRTOVALMAP::emplace (key_type&& key,
723  std::unique_ptr<mapped_type> val,
724  const Context_t& ctx
725  /*= Updater_t::defaultContext()*/)
726  -> std::pair<const_iterator, bool>
727 {
728  return put (std::make_unique<key_type> (std::move (key)),
729  std::move (val),
730  ctx);
731 }
732 
733 
734 /**
735  * @brief Add an element to the map.
736  * @param p The item to add.
737  * Should be a pair where first is the string key
738  * and second is the integer value.
739  * @param ctx Execution context.
740  *
741  * This will not overwrite an existing entry.
742  * The first element in the returned pair is an iterator referencing
743  * the added item. The second is a flag that is true if a new element
744  * was added.
745  */
746 T_CONCURRENTSTRTOVALMAP
747 template <class PAIR>
748 inline
749 auto CONCURRENTSTRTOVALMAP::insert (const PAIR& p,
750  const Context_t& ctx /*= Updater_t::defaultContext()*/)
751  -> std::pair<const_iterator, bool>
752 {
753  return emplace (p.first, p.second, ctx);
754 }
755 
756 
757 /**
758  * @brief Add an element to the map.
759  * @param p The item to add.
760  * Should be a pair where first is the string key
761  * and second is the integer value.
762  * @param ctx Execution context.
763  *
764  * This will not overwrite an existing entry.
765  * The first element in the returned pair is an iterator referencing
766  * the added item. The second is a flag that is true if a new element
767  * was added.
768  */
769 T_CONCURRENTSTRTOVALMAP
770 template <class PAIR>
771 inline
772 auto CONCURRENTSTRTOVALMAP::insert (PAIR&& p,
773  const Context_t& ctx /*= Updater_t::defaultContext()*/)
774  -> std::pair<const_iterator, bool>
775 {
776  return emplace (std::move (p.first), std::move (p.second), ctx);
777 }
778 
779 
780 /**
781  * @brief Insert a range of elements to the map.
782  * @param first Start of the range.
783  * @param last End of the range.
784  * @param ctx Execution context.
785  *
786  * The range should be a sequence of pairs where first is the string key
787  * and second is the integer value.
788  */
789 T_CONCURRENTSTRTOVALMAP
790 template <class InputIterator>
791 void CONCURRENTSTRTOVALMAP::insert (InputIterator first, InputIterator last,
792  const Context_t& ctx /*= Updater_t::defaultContext()*/)
793 {
794  if constexpr (std::is_rvalue_reference_v<typename InputIterator::reference>)
795  {
796  for (; first != last; ++first) {
797  emplace (std::move (first->first), std::move (first->second), ctx);
798  }
799  }
800  else {
801  for (; first != last; ++first) {
802  emplace (first->first, first->second, ctx);
803  }
804  }
805 }
806 
807 
808 /**
809  * @brief Increase the table capacity.
810  * @param capacity The new table capacity.
811  * @param ctx Execution context.
812  *
813  * No action will be taken if @c capacity is smaller
814  * than the current capacity.
815  */
816 T_CONCURRENTSTRTOVALMAP
817 inline
818 void CONCURRENTSTRTOVALMAP::reserve (size_type capacity,
819  const Context_t& ctx
820  /*= Updater_t::defaultContext()*/)
821 {
822  return m_impl.reserve (capacity, ctx);
823 }
824 
825 
826 /**
827  * @brief Increase the table capacity.
828  * @param capacity The new table capacity.
829  *
830  * No action will be taken if @c capacity is smaller
831  * than the current capacity.
832  */
833 T_CONCURRENTSTRTOVALMAP
834 inline
835 void CONCURRENTSTRTOVALMAP::rehash (size_type capacity)
836 {
837  return reserve (capacity);
838 }
839 
840 
841 /**
842  * @brief Called when this thread is no longer referencing anything
843  * from this container.
844  * @param ctx Execution context.
845  */
846 T_CONCURRENTSTRTOVALMAP
847 inline
848 void CONCURRENTSTRTOVALMAP::quiescent (const Context_t& ctx)
849 {
850  return m_impl.quiescent (ctx);
851 }
852 
853 
854 /**
855  * @brief Swap this container with another.
856  * @param other The container with which to swap.
857  *
858  * This will also call swap on the Updater object; hence, the Updater
859  * object must also support swap.
860  *
861  * This operation is NOT thread-safe. No other threads may be accessing
862  * either container during this operation.
863  */
864 T_CONCURRENTSTRTOVALMAP
865 void CONCURRENTSTRTOVALMAP::swap (ConcurrentStrToValMap& other)
866 {
867  m_impl.swap (other.m_impl);
868 }
869 
870 
871 /**
872  * @brief Access the Updater instance.
873  */
874 T_CONCURRENTSTRTOVALMAP
875 auto CONCURRENTSTRTOVALMAP::updater() -> Updater_t&
876 {
877  return m_impl.updater();
878 }
879 
880 
881 /**
882  * @brief Convert an underlying key value to a string pointer.
883  * @param val The underlying key value.
884  */
885 T_CONCURRENTSTRTOVALMAP
886 inline
887 auto CONCURRENTSTRTOVALMAP::keyAsString (val_t val) -> const std::string*
888 {
889  return reinterpret_cast<std::string*> (val);
890 }
891 
892 
893 /**
894  * @brief Convert a string pointer to an underlying key value.
895  * @param s The string pointer.
896  */
897 T_CONCURRENTSTRTOVALMAP
898 inline
899 auto CONCURRENTSTRTOVALMAP::keyAsVal (const std::string* s) -> val_t
900 {
901  return reinterpret_cast<val_t> (s);
902 }
903 
904 
905 /**
906  * @brief Convert an underlying mapped value a pointer to
907  * this type's mapped value.
908  * @param val The underlying mapped value.
909  */
910 T_CONCURRENTSTRTOVALMAP
911 inline
912 auto CONCURRENTSTRTOVALMAP::mappedAsMapped (val_t val) -> mapped_type*
913 {
914  return CxxUtils::detail::UIntConv<mapped_type*>::uintToVal (val);
915 }
916 
917 
918 /**
919  * @brief Convert this type's mapped value to an underlying mapped value.
920  * @param val The mapped value.
921  */
922 T_CONCURRENTSTRTOVALMAP
923 inline
924 auto CONCURRENTSTRTOVALMAP::mappedAsVal (mapped_type* val) -> val_t
925 {
926  return CxxUtils::detail::UIntConv<mapped_type*>::valToUInt (val);
927 }
928 
929 
930 /**
931  * @brief Do a lookup in the table.
932  * @param key The key to look up.
933  *
934  * Returns an iterator of the underlying map pointing at the found
935  * entry or end();
936  */
937 T_CONCURRENTSTRTOVALMAP
938 auto CONCURRENTSTRTOVALMAP::get (const key_type& key) const
939  -> typename Impl_t::const_iterator
940 {
941  size_t hash = m_impl.hasher() (key);
942  return m_impl.get (keyAsVal(&key), hash);
943 }
944 
945 
946 /**
947  * @brief Insert an entry in the table.
948  * @param key The key of the new item to add.
949  * @param val The new mapped value to add.
950  * @param ctx Execution context.
951  *
952  * The first element in the returned pair is an iterator referencing
953  * the added item. The second is a flag that is true if a new element
954  * was added.
955  */
956 T_CONCURRENTSTRTOVALMAP
957 auto CONCURRENTSTRTOVALMAP::put (std::unique_ptr<key_type> key,
958  std::unique_ptr<mapped_type> val,
959  const Context_t& ctx /*= Updater_t::defaultContext()*/)
960  -> std::pair<const_iterator, bool>
961 {
962  size_t hash = m_impl.hasher() (*key);
963  auto [it, flag] = m_impl.put (keyAsVal(key.get()), hash,
964  mappedAsVal (val.get()),
965  false, ctx);
966  if (flag) {
967  key.release();
968  val.release();
969  }
970 
971  return std::make_pair (const_iterator (it), flag);
972 }
973 
974 
975 /**
976  * @brief Hash function from the underlying representation type.
977  */
978 T_CONCURRENTSTRTOVALMAP
979 inline
980 auto CONCURRENTSTRTOVALMAP::Hasher::operator() (const val_t p) const -> size_t
981 {
982  return m_hash (*keyAsString(p));
983 }
984 
985 
986 /**
987  * @brief Hash function from a std::string.
988  */
989 T_CONCURRENTSTRTOVALMAP
990 inline
991 auto CONCURRENTSTRTOVALMAP::Hasher::operator() (const std::string& s) const -> size_t
992 {
993  return m_hash (s);
994 }
995 
996 
997 /**
998  * @brief Compare two keys (as the underlying representation type) for equality.
999  */
1000 T_CONCURRENTSTRTOVALMAP
1001 inline
1002 auto CONCURRENTSTRTOVALMAP::Matcher::operator() (const val_t a, const val_t b) const -> bool
1003 {
1004  // First test if the keys (pointers) themselves are equal.
1005  if (a == b) return true;
1006  // Otherwise, need to test the strings to which they point.
1007  return *keyAsString(a) == *keyAsString(b);
1008 }
1009 
1010 
1011 #undef T_CONCURRENTSTRTOVALMAP
1012 #undef CONCURRENTSTRTOVALMAP
1013 
1014 
1015 } // namespace CxxUtils