ATLAS Offline Software
Loading...
Searching...
No Matches
ConcurrentStrToValMap.icc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2025 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
13namespace CxxUtils {
14
15
16#define T_CONCURRENTSTRTOVALMAP template <class VALUE, \
17 template <class> class UPDATER> \
18 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 */
31T_CONCURRENTSTRTOVALMAP
32CONCURRENTSTRTOVALMAP::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 */
55T_CONCURRENTSTRTOVALMAP
56CONCURRENTSTRTOVALMAP::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 */
88T_CONCURRENTSTRTOVALMAP
89template <class InputIterator>
90CONCURRENTSTRTOVALMAP::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 */
119T_CONCURRENTSTRTOVALMAP
120CONCURRENTSTRTOVALMAP::~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 */
137T_CONCURRENTSTRTOVALMAP
138inline
139auto 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 */
148T_CONCURRENTSTRTOVALMAP
149inline
150bool 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 */
159T_CONCURRENTSTRTOVALMAP
160inline
161auto 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 */
171T_CONCURRENTSTRTOVALMAP
172inline
173CONCURRENTSTRTOVALMAP::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 */
183T_CONCURRENTSTRTOVALMAP
184inline
185CONCURRENTSTRTOVALMAP::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 */
196T_CONCURRENTSTRTOVALMAP
197inline
198auto 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 */
207T_CONCURRENTSTRTOVALMAP
208inline
209auto CONCURRENTSTRTOVALMAP::const_iterator::increment() -> void
210{
211 m_impl.next();
212}
213
214
215/**
216 * @brief iterator_facade requirement: Decrement the iterator.
217 */
218T_CONCURRENTSTRTOVALMAP
219inline
220auto CONCURRENTSTRTOVALMAP::const_iterator::decrement() -> void
221{
222 m_impl.prev();
223}
224
225
226/**
227 * @brief iterator_facade requirement: Dereference the iterator.
228 */
229T_CONCURRENTSTRTOVALMAP
230inline
231auto 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 */
242T_CONCURRENTSTRTOVALMAP
243inline
244auto 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 */
254T_CONCURRENTSTRTOVALMAP
255inline
256auto 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 */
267T_CONCURRENTSTRTOVALMAP
268inline
269CONCURRENTSTRTOVALMAP::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 */
280T_CONCURRENTSTRTOVALMAP
281inline
282auto CONCURRENTSTRTOVALMAP::iterator::valid() const -> bool
283{
284 return m_impl.valid();
285}
286
287
288/**
289 * @brief iterator_facade requirement: Increment the iterator.
290 */
291T_CONCURRENTSTRTOVALMAP
292inline
293auto CONCURRENTSTRTOVALMAP::iterator::increment() -> void
294{
295 m_impl.next();
296}
297
298
299/**
300 * @brief iterator_facade requirement: Decrement the iterator.
301 */
302T_CONCURRENTSTRTOVALMAP
303inline
304auto CONCURRENTSTRTOVALMAP::iterator::decrement() -> void
305{
306 m_impl.prev();
307}
308
309
310/**
311 * @brief iterator_facade requirement: Dereference the iterator.
312 */
313T_CONCURRENTSTRTOVALMAP
314inline
315auto 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 */
326T_CONCURRENTSTRTOVALMAP
327inline
328auto 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 */
338T_CONCURRENTSTRTOVALMAP
339inline
340auto 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 */
350T_CONCURRENTSTRTOVALMAP
351auto 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 */
364T_CONCURRENTSTRTOVALMAP
365auto 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 */
375T_CONCURRENTSTRTOVALMAP
376inline
377auto 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 */
386T_CONCURRENTSTRTOVALMAP
387inline
388auto 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 */
400T_CONCURRENTSTRTOVALMAP
401inline
402auto 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 */
414T_CONCURRENTSTRTOVALMAP
415inline
416auto CONCURRENTSTRTOVALMAP::end() -> iterator
417{
418 return iterator (m_impl.end());
419}
420
421
422/**
423 * @brief Iterator at the start of the map.
424 */
425T_CONCURRENTSTRTOVALMAP
426inline
427auto CONCURRENTSTRTOVALMAP::cbegin() const -> const_iterator
428{
429 return begin();
430}
431
432
433/**
434 * @brief Iterator at the end of the map.
435 */
436T_CONCURRENTSTRTOVALMAP
437inline
438auto 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 */
448T_CONCURRENTSTRTOVALMAP
449inline
450bool 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 */
462T_CONCURRENTSTRTOVALMAP
463inline
464auto 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 */
476T_CONCURRENTSTRTOVALMAP
477inline
478auto 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 */
493T_CONCURRENTSTRTOVALMAP
494inline
495auto 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 */
508T_CONCURRENTSTRTOVALMAP
509auto 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 */
530T_CONCURRENTSTRTOVALMAP
531auto 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 */
548T_CONCURRENTSTRTOVALMAP
549auto 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 */
571T_CONCURRENTSTRTOVALMAP
572auto 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 */
595T_CONCURRENTSTRTOVALMAP
596inline
597auto 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 */
620T_CONCURRENTSTRTOVALMAP
621inline
622auto 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 */
645T_CONCURRENTSTRTOVALMAP
646inline
647auto 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 */
670T_CONCURRENTSTRTOVALMAP
671inline
672auto 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 */
695T_CONCURRENTSTRTOVALMAP
696inline
697auto 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 */
720T_CONCURRENTSTRTOVALMAP
721inline
722auto 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 */
746T_CONCURRENTSTRTOVALMAP
747template <class PAIR>
748inline
749auto 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 */
769T_CONCURRENTSTRTOVALMAP
770template <class PAIR>
771inline
772auto 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 */
789T_CONCURRENTSTRTOVALMAP
790template <class InputIterator>
791void 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 */
816T_CONCURRENTSTRTOVALMAP
817inline
818void 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 */
833T_CONCURRENTSTRTOVALMAP
834inline
835void 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 */
846T_CONCURRENTSTRTOVALMAP
847inline
848void 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 */
864T_CONCURRENTSTRTOVALMAP
865void CONCURRENTSTRTOVALMAP::swap (ConcurrentStrToValMap& other)
866{
867 m_impl.swap (other.m_impl);
868}
869
870
871/**
872 * @brief Access the Updater instance.
873 */
874T_CONCURRENTSTRTOVALMAP
875auto 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 */
885T_CONCURRENTSTRTOVALMAP
886inline
887auto 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 */
897T_CONCURRENTSTRTOVALMAP
898inline
899auto 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 */
910T_CONCURRENTSTRTOVALMAP
911inline
912auto 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 */
922T_CONCURRENTSTRTOVALMAP
923inline
924auto 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 */
937T_CONCURRENTSTRTOVALMAP
938auto 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 */
956T_CONCURRENTSTRTOVALMAP
957auto 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 */
978T_CONCURRENTSTRTOVALMAP
979inline
980auto 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 */
989T_CONCURRENTSTRTOVALMAP
990inline
991auto 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 */
1000T_CONCURRENTSTRTOVALMAP
1001inline
1002auto 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