rippled
Loading...
Searching...
No Matches
aged_unordered_container.h
1#pragma once
2
3#include <xrpl/beast/clock/abstract_clock.h>
4#include <xrpl/beast/container/aged_container.h>
5#include <xrpl/beast/container/detail/aged_associative_container.h>
6#include <xrpl/beast/container/detail/aged_container_iterator.h>
7#include <xrpl/beast/container/detail/empty_base_optimization.h>
8
9#include <boost/intrusive/list.hpp>
10#include <boost/intrusive/unordered_set.hpp>
11
12#include <algorithm>
13#include <cmath>
14#include <functional>
15#include <initializer_list>
16#include <iterator>
17#include <memory>
18#include <type_traits>
19#include <utility>
20
21/*
22
23TODO
24
25- Add constructor variations that take a bucket count
26
27- Review for noexcept and exception guarantees
28
29- Call the safe version of is_permutation that takes 4 iterators
30
31*/
32
33#ifndef BEAST_NO_CXX14_IS_PERMUTATION
34#define BEAST_NO_CXX14_IS_PERMUTATION 1
35#endif
36
37namespace beast {
38namespace detail {
39
57template <
58 bool IsMulti,
59 bool IsMap,
60 class Key,
61 class T,
62 class Clock = std::chrono::steady_clock,
63 class Hash = std::hash<Key>,
64 class KeyEqual = std::equal_to<Key>,
67{
68public:
72 using key_type = Key;
73 using mapped_type = T;
77
78 // Introspection (for unit tests)
82
83private:
84 static Key const&
85 extract(value_type const& value)
86 {
88 }
89
90 // VFALCO TODO hoist to remove template argument dependencies
91 struct element
92 : boost::intrusive::unordered_set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>,
93 boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>
94 {
95 // Stash types here so the iterator doesn't
96 // need to see the container declaration.
97 struct stashed
98 {
99 explicit stashed() = default;
100
103 };
104
105 element(time_point const& when_, value_type const& value_) : value(value_), when(when_)
106 {
107 }
108
109 element(time_point const& when_, value_type&& value_) : value(std::move(value_)), when(when_)
110 {
111 }
112
113 template <
114 class... Args,
115 class = typename std::enable_if<std::is_constructible<value_type, Args...>::value>::type>
116 element(time_point const& when_, Args&&... args) : value(std::forward<Args>(args)...), when(when_)
117 {
118 }
119
122 };
123
124 // VFALCO TODO hoist to remove template argument dependencies
125 class ValueHash : public Hash
126 {
127 public:
129 using result_type = size_t;
130
132 {
133 }
134
135 ValueHash(Hash const& h) : Hash(h)
136 {
137 }
138
140 operator()(element const& e) const
141 {
142 return Hash::operator()(extract(e.value));
143 }
144
145 Hash&
147 {
148 return *this;
149 }
150
151 Hash const&
153 {
154 return *this;
155 }
156 };
157
158 // Compares value_type against element, used in find/insert_check
159 // VFALCO TODO hoist to remove template argument dependencies
160 class KeyValueEqual : public KeyEqual
161 {
162 public:
165 using result_type = bool;
166
168 {
169 }
170
171 KeyValueEqual(KeyEqual const& keyEqual) : KeyEqual(keyEqual)
172 {
173 }
174
175 bool
176 operator()(Key const& k, element const& e) const
177 {
178 return KeyEqual::operator()(k, extract(e.value));
179 }
180
181 bool
182 operator()(element const& e, Key const& k) const
183 {
184 return KeyEqual::operator()(extract(e.value), k);
185 }
186
187 bool
188 operator()(element const& lhs, element const& rhs) const
189 {
190 return KeyEqual::operator()(extract(lhs.value), extract(rhs.value));
191 }
192
193 KeyEqual&
195 {
196 return *this;
197 }
198
199 KeyEqual const&
200 key_eq() const
201 {
202 return *this;
203 }
204 };
205
206 using list_type = typename boost::intrusive::make_list<element, boost::intrusive::constant_time_size<false>>::type;
207
208 using cont_type = typename std::conditional<
209 IsMulti,
210 typename boost::intrusive::make_unordered_multiset<
211 element,
212 boost::intrusive::constant_time_size<true>,
213 boost::intrusive::hash<ValueHash>,
214 boost::intrusive::equal<KeyValueEqual>,
215 boost::intrusive::cache_begin<true>>::type,
216 typename boost::intrusive::make_unordered_set<
217 element,
218 boost::intrusive::constant_time_size<true>,
219 boost::intrusive::hash<ValueHash>,
220 boost::intrusive::equal<KeyValueEqual>,
221 boost::intrusive::cache_begin<true>>::type>::type;
222
223 using bucket_type = typename cont_type::bucket_type;
224 using bucket_traits = typename cont_type::bucket_traits;
225
226 using ElementAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<element>;
227
229
230 using BucketAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<element>;
231
233
234 class config_t : private ValueHash,
235 private KeyValueEqual,
236 private beast::detail::empty_base_optimization<ElementAllocator>
237 {
238 public:
239 explicit config_t(clock_type& clock_) : clock(clock_)
240 {
241 }
242
243 config_t(clock_type& clock_, Hash const& hash) : ValueHash(hash), clock(clock_)
244 {
245 }
246
247 config_t(clock_type& clock_, KeyEqual const& keyEqual) : KeyValueEqual(keyEqual), clock(clock_)
248 {
249 }
250
251 config_t(clock_type& clock_, Allocator const& alloc_)
252 : beast::detail::empty_base_optimization<ElementAllocator>(alloc_), clock(clock_)
253 {
254 }
255
256 config_t(clock_type& clock_, Hash const& hash, KeyEqual const& keyEqual)
257 : ValueHash(hash), KeyValueEqual(keyEqual), clock(clock_)
258 {
259 }
260
261 config_t(clock_type& clock_, Hash const& hash, Allocator const& alloc_)
262 : ValueHash(hash), beast::detail::empty_base_optimization<ElementAllocator>(alloc_), clock(clock_)
263 {
264 }
265
266 config_t(clock_type& clock_, KeyEqual const& keyEqual, Allocator const& alloc_)
267 : KeyValueEqual(keyEqual), beast::detail::empty_base_optimization<ElementAllocator>(alloc_), clock(clock_)
268 {
269 }
270
271 config_t(clock_type& clock_, Hash const& hash, KeyEqual const& keyEqual, Allocator const& alloc_)
272 : ValueHash(hash)
273 , KeyValueEqual(keyEqual)
275 , clock(clock_)
276 {
277 }
278
279 config_t(config_t const& other)
280 : ValueHash(other.hash_function())
281 , KeyValueEqual(other.key_eq())
283 ElementAllocatorTraits::select_on_container_copy_construction(other.alloc()))
284 , clock(other.clock)
285 {
286 }
287
288 config_t(config_t const& other, Allocator const& alloc)
289 : ValueHash(other.hash_function())
290 , KeyValueEqual(other.key_eq())
292 , clock(other.clock)
293 {
294 }
295
297 : ValueHash(std::move(other.hash_function()))
298 , KeyValueEqual(std::move(other.key_eq()))
299 , beast::detail::empty_base_optimization<ElementAllocator>(std::move(other.alloc()))
300 , clock(other.clock)
301 {
302 }
303
304 config_t(config_t&& other, Allocator const& alloc)
305 : ValueHash(std::move(other.hash_function()))
306 , KeyValueEqual(std::move(other.key_eq()))
308 , clock(other.clock)
309 {
310 }
311
312 config_t&
313 operator=(config_t const& other)
314 {
315 hash_function() = other.hash_function();
316 key_eq() = other.key_eq();
317 alloc() = other.alloc();
318 clock = other.clock;
319 return *this;
320 }
321
322 config_t&
324 {
325 hash_function() = std::move(other.hash_function());
326 key_eq() = std::move(other.key_eq());
327 alloc() = std::move(other.alloc());
328 clock = other.clock;
329 return *this;
330 }
331
332 ValueHash&
334 {
335 return *this;
336 }
337
338 ValueHash const&
340 {
341 return *this;
342 }
343
344 Hash&
346 {
348 }
349
350 Hash const&
352 {
354 }
355
358 {
359 return *this;
360 }
361
362 KeyValueEqual const&
364 {
365 return *this;
366 }
367
368 KeyEqual&
370 {
371 return key_value_equal().key_eq();
372 }
373
374 KeyEqual const&
375 key_eq() const
376 {
377 return key_value_equal().key_eq();
378 }
379
385
386 ElementAllocator const&
391
393 };
394
396 {
397 public:
398 using vec_type =
400
402 {
403 m_vec.resize(cont_type::suggested_upper_bucket_count(0));
404 }
405
406 Buckets(Allocator const& alloc) : m_max_load_factor(1.f), m_vec(alloc)
407 {
408 m_vec.resize(cont_type::suggested_upper_bucket_count(0));
409 }
410
411 operator bucket_traits()
412 {
413 return bucket_traits(&m_vec[0], m_vec.size());
414 }
415
416 void
418 {
419 m_vec.clear();
420 }
421
424 {
425 return m_vec.max_size();
426 }
427
428 float&
430 {
431 return m_max_load_factor;
432 }
433
434 float const&
436 {
437 return m_max_load_factor;
438 }
439
440 // count is the number of buckets
441 template <class Container>
442 void
443 rehash(size_type count, Container& c)
444 {
445 size_type const size(m_vec.size());
446 if (count == size)
447 return;
448 if (count > m_vec.capacity())
449 {
450 // Need two vectors otherwise we
451 // will destroy non-empty buckets.
453 std::swap(m_vec, vec);
455 c.rehash(bucket_traits(&m_vec[0], m_vec.size()));
456 return;
457 }
458 // Rehash in place.
459 if (count > size)
460 {
461 // This should not reallocate since
462 // we checked capacity earlier.
464 c.rehash(bucket_traits(&m_vec[0], count));
465 return;
466 }
467 // Resize must happen after rehash otherwise
468 // we might destroy non-empty buckets.
469 c.rehash(bucket_traits(&m_vec[0], count));
471 }
472
473 // Resize the buckets to accommodate at least n items.
474 template <class Container>
475 void
476 resize(size_type n, Container& c)
477 {
478 size_type const suggested(cont_type::suggested_upper_bucket_count(n));
479 rehash(suggested, c);
480 }
481
482 private:
485 };
486
487 template <class... Args>
488 element*
489 new_element(Args&&... args)
490 {
491 struct Deleter
492 {
494 Deleter(ElementAllocator& a) : a_(a)
495 {
496 }
497
498 void
499 operator()(element* p)
500 {
501 ElementAllocatorTraits::deallocate(a_.get(), p, 1);
502 }
503 };
504
508 return p.release();
509 }
510
511 void
517
518 void
520 {
521 chronological.list.erase(chronological.list.iterator_to(*p));
522 m_cont.erase(m_cont.iterator_to(*p));
524 }
525
526public:
527 using hasher = Hash;
528 using key_equal = KeyEqual;
529 using allocator_type = Allocator;
534
535 // A set iterator (IsMap==false) is always const
536 // because the elements of a set are immutable.
539
542
543 //--------------------------------------------------------------------------
544 //
545 // Chronological ordered iterators
546 //
547 // "Memberspace"
548 // http://accu.org/index.php/journals/1527
549 //
550 //--------------------------------------------------------------------------
551
553 {
554 public:
555 // A set iterator (IsMap==false) is always const
556 // because the elements of a set are immutable.
562
565 {
566 return iterator(list.begin());
567 }
568
570 begin() const
571 {
572 return const_iterator(list.begin());
573 }
574
576 cbegin() const
577 {
578 return const_iterator(list.begin());
579 }
580
583 {
584 return iterator(list.end());
585 }
586
588 end() const
589 {
590 return const_iterator(list.end());
591 }
592
594 cend() const
595 {
596 return const_iterator(list.end());
597 }
598
601 {
602 return reverse_iterator(list.rbegin());
603 }
604
606 rbegin() const
607 {
608 return const_reverse_iterator(list.rbegin());
609 }
610
612 crbegin() const
613 {
614 return const_reverse_iterator(list.rbegin());
615 }
616
619 {
620 return reverse_iterator(list.rend());
621 }
622
624 rend() const
625 {
626 return const_reverse_iterator(list.rend());
627 }
628
630 crend() const
631 {
632 return const_reverse_iterator(list.rend());
633 }
634
637 {
638 static_assert(std::is_standard_layout<element>::value, "must be standard layout");
639 return list.iterator_to(*reinterpret_cast<element*>(
640 reinterpret_cast<uint8_t*>(&value) - ((std::size_t)std::addressof(((element*)0)->member))));
641 }
642
644 iterator_to(value_type const& value) const
645 {
646 static_assert(std::is_standard_layout<element>::value, "must be standard layout");
647 return list.iterator_to(*reinterpret_cast<element const*>(
648 reinterpret_cast<uint8_t const*>(&value) - ((std::size_t)std::addressof(((element*)0)->member))));
649 }
650
651 private:
653 {
654 }
655
658
662
663 //--------------------------------------------------------------------------
664 //
665 // Construction
666 //
667 //--------------------------------------------------------------------------
668
670
672
674
676
677 aged_unordered_container(clock_type& clock, Allocator const& alloc);
678
679 aged_unordered_container(clock_type& clock, Hash const& hash, KeyEqual const& key_eq);
680
681 aged_unordered_container(clock_type& clock, Hash const& hash, Allocator const& alloc);
682
683 aged_unordered_container(clock_type& clock, KeyEqual const& key_eq, Allocator const& alloc);
684
685 aged_unordered_container(clock_type& clock, Hash const& hash, KeyEqual const& key_eq, Allocator const& alloc);
686
687 template <class InputIt>
688 aged_unordered_container(InputIt first, InputIt last, clock_type& clock);
689
690 template <class InputIt>
691 aged_unordered_container(InputIt first, InputIt last, clock_type& clock, Hash const& hash);
692
693 template <class InputIt>
694 aged_unordered_container(InputIt first, InputIt last, clock_type& clock, KeyEqual const& key_eq);
695
696 template <class InputIt>
697 aged_unordered_container(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc);
698
699 template <class InputIt>
700 aged_unordered_container(InputIt first, InputIt last, clock_type& clock, Hash const& hash, KeyEqual const& key_eq);
701
702 template <class InputIt>
703 aged_unordered_container(InputIt first, InputIt last, clock_type& clock, Hash const& hash, Allocator const& alloc);
704
705 template <class InputIt>
707 InputIt first,
708 InputIt last,
710 KeyEqual const& key_eq,
711 Allocator const& alloc);
712
713 template <class InputIt>
715 InputIt first,
716 InputIt last,
718 Hash const& hash,
719 KeyEqual const& key_eq,
720 Allocator const& alloc);
721
723
724 aged_unordered_container(aged_unordered_container const& other, Allocator const& alloc);
725
727
728 aged_unordered_container(aged_unordered_container&& other, Allocator const& alloc);
729
731
733
735
737
741 Hash const& hash,
742 KeyEqual const& key_eq);
743
747 Hash const& hash,
748 Allocator const& alloc);
749
753 KeyEqual const& key_eq,
754 Allocator const& alloc);
755
759 Hash const& hash,
760 KeyEqual const& key_eq,
761 Allocator const& alloc);
762
764
767
770
773
776 {
777 return m_config.alloc();
778 }
779
782 {
783 return m_config.clock;
784 }
785
786 clock_type const&
787 clock() const
788 {
789 return m_config.clock;
790 }
791
792 //--------------------------------------------------------------------------
793 //
794 // Element access (maps)
795 //
796 //--------------------------------------------------------------------------
797
798 template <
799 class K,
800 bool maybe_multi = IsMulti,
801 bool maybe_map = IsMap,
804 at(K const& k);
805
806 template <
807 class K,
808 bool maybe_multi = IsMulti,
809 bool maybe_map = IsMap,
812 at(K const& k) const;
813
814 template <
815 bool maybe_multi = IsMulti,
816 bool maybe_map = IsMap,
819 operator[](Key const& key);
820
821 template <
822 bool maybe_multi = IsMulti,
823 bool maybe_map = IsMap,
826 operator[](Key&& key);
827
828 //--------------------------------------------------------------------------
829 //
830 // Iterators
831 //
832 //--------------------------------------------------------------------------
833
836 {
837 return iterator(m_cont.begin());
838 }
839
841 begin() const
842 {
843 return const_iterator(m_cont.begin());
844 }
845
847 cbegin() const
848 {
849 return const_iterator(m_cont.begin());
850 }
851
854 {
855 return iterator(m_cont.end());
856 }
857
859 end() const
860 {
861 return const_iterator(m_cont.end());
862 }
863
865 cend() const
866 {
867 return const_iterator(m_cont.end());
868 }
869
872 {
873 static_assert(std::is_standard_layout<element>::value, "must be standard layout");
874 return m_cont.iterator_to(*reinterpret_cast<element*>(
875 reinterpret_cast<uint8_t*>(&value) - ((std::size_t)std::addressof(((element*)0)->member))));
876 }
877
879 iterator_to(value_type const& value) const
880 {
881 static_assert(std::is_standard_layout<element>::value, "must be standard layout");
882 return m_cont.iterator_to(*reinterpret_cast<element const*>(
883 reinterpret_cast<uint8_t const*>(&value) - ((std::size_t)std::addressof(((element*)0)->member))));
884 }
885
886 //--------------------------------------------------------------------------
887 //
888 // Capacity
889 //
890 //--------------------------------------------------------------------------
891
892 bool
893 empty() const noexcept
894 {
895 return m_cont.empty();
896 }
897
899 size() const noexcept
900 {
901 return m_cont.size();
902 }
903
905 max_size() const noexcept
906 {
907 return m_config.max_size();
908 }
909
910 //--------------------------------------------------------------------------
911 //
912 // Modifiers
913 //
914 //--------------------------------------------------------------------------
915
916 void
918
919 // map, set
920 template <bool maybe_multi = IsMulti>
921 auto
923
924 // multimap, multiset
925 template <bool maybe_multi = IsMulti>
926 auto
928
929 // map, set
930 template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
931 auto
933
934 // multimap, multiset
935 template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
936 auto
938
939 // map, set
940 template <bool maybe_multi = IsMulti>
942 insert(const_iterator /*hint*/, value_type const& value)
943 {
944 // Hint is ignored but we provide the interface so
945 // callers may use ordered and unordered interchangeably.
946 return insert(value).first;
947 }
948
949 // multimap, multiset
950 template <bool maybe_multi = IsMulti>
952 insert(const_iterator /*hint*/, value_type const& value)
953 {
954 // VFALCO TODO The hint could be used to let
955 // the client order equal ranges
956 return insert(value);
957 }
958
959 // map, set
960 template <bool maybe_multi = IsMulti>
963 {
964 // Hint is ignored but we provide the interface so
965 // callers may use ordered and unordered interchangeably.
966 return insert(std::move(value)).first;
967 }
968
969 // multimap, multiset
970 template <bool maybe_multi = IsMulti>
973 {
974 // VFALCO TODO The hint could be used to let
975 // the client order equal ranges
976 return insert(std::move(value));
977 }
978
979 // map, multimap
980 template <class P, bool maybe_map = IsMap>
981 typename std::enable_if<
984 insert(P&& value)
985 {
986 return emplace(std::forward<P>(value));
987 }
988
989 // map, multimap
990 template <class P, bool maybe_map = IsMap>
991 typename std::enable_if<
994 insert(const_iterator hint, P&& value)
995 {
996 return emplace_hint(hint, std::forward<P>(value));
997 }
998
999 template <class InputIt>
1000 void
1001 insert(InputIt first, InputIt last)
1002 {
1004 }
1005
1006 void
1008 {
1009 insert(init.begin(), init.end());
1010 }
1011
1012 // set, map
1013 template <bool maybe_multi = IsMulti, class... Args>
1014 auto
1016
1017 // multiset, multimap
1018 template <bool maybe_multi = IsMulti, class... Args>
1019 auto
1021
1022 // set, map
1023 template <bool maybe_multi = IsMulti, class... Args>
1024 auto
1025 emplace_hint(const_iterator /*hint*/, Args&&... args) ->
1027
1028 // multiset, multimap
1029 template <bool maybe_multi = IsMulti, class... Args>
1031 emplace_hint(const_iterator /*hint*/, Args&&... args)
1032 {
1033 // VFALCO TODO The hint could be used for multi, to let
1034 // the client order equal ranges
1035 return emplace<maybe_multi>(std::forward<Args>(args)...);
1036 }
1037
1038 template <bool is_const, class Iterator>
1041
1042 template <bool is_const, class Iterator>
1047
1048 template <class K>
1049 auto
1050 erase(K const& k) -> size_type;
1051
1052 void
1054
1055 template <bool is_const, class Iterator>
1056 void
1061
1062 template <class K>
1063 auto
1064 touch(K const& k) -> size_type;
1065
1066 //--------------------------------------------------------------------------
1067 //
1068 // Lookup
1069 //
1070 //--------------------------------------------------------------------------
1071
1072 // VFALCO TODO Respect is_transparent (c++14)
1073 template <class K>
1074 size_type
1075 count(K const& k) const
1076 {
1078 }
1079
1080 // VFALCO TODO Respect is_transparent (c++14)
1081 template <class K>
1082 iterator
1083 find(K const& k)
1084 {
1086 }
1087
1088 // VFALCO TODO Respect is_transparent (c++14)
1089 template <class K>
1091 find(K const& k) const
1092 {
1093 return const_iterator(
1095 }
1096
1097 // VFALCO TODO Respect is_transparent (c++14)
1098 template <class K>
1100 equal_range(K const& k)
1101 {
1102 auto const r(m_cont.equal_range(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal())));
1103 return std::make_pair(iterator(r.first), iterator(r.second));
1104 }
1105
1106 // VFALCO TODO Respect is_transparent (c++14)
1107 template <class K>
1109 equal_range(K const& k) const
1110 {
1111 auto const r(m_cont.equal_range(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal())));
1112 return std::make_pair(const_iterator(r.first), const_iterator(r.second));
1113 }
1114
1115 //--------------------------------------------------------------------------
1116 //
1117 // Bucket interface
1118 //
1119 //--------------------------------------------------------------------------
1120
1123 {
1124 return local_iterator(m_cont.begin(n));
1125 }
1126
1129 {
1130 return const_local_iterator(m_cont.begin(n));
1131 }
1132
1135 {
1136 return const_local_iterator(m_cont.begin(n));
1137 }
1138
1141 {
1142 return local_iterator(m_cont.end(n));
1143 }
1144
1147 {
1148 return const_local_iterator(m_cont.end(n));
1149 }
1150
1153 {
1154 return const_local_iterator(m_cont.end(n));
1155 }
1156
1157 size_type
1159 {
1160 return m_cont.bucket_count();
1161 }
1162
1163 size_type
1165 {
1166 return m_buck.max_bucket_count();
1167 }
1168
1169 size_type
1171 {
1172 return m_cont.bucket_size(n);
1173 }
1174
1175 size_type
1176 bucket(Key const& k) const
1177 {
1178 XRPL_ASSERT(
1179 bucket_count() != 0,
1180 "beast::detail::aged_unordered_container::bucket : nonzero bucket "
1181 "count");
1182 return m_cont.bucket(k, std::cref(m_config.hash_function()));
1183 }
1184
1185 //--------------------------------------------------------------------------
1186 //
1187 // Hash policy
1188 //
1189 //--------------------------------------------------------------------------
1190
1191 float
1193 {
1194 return size() / static_cast<float>(m_cont.bucket_count());
1195 }
1196
1197 float
1199 {
1200 return m_buck.max_load_factor();
1201 }
1202
1203 void
1205 {
1207 }
1208
1209 void
1215
1216 void
1221
1222 //--------------------------------------------------------------------------
1223 //
1224 // Observers
1225 //
1226 //--------------------------------------------------------------------------
1227
1228 hasher const&
1230 {
1231 return m_config.hash_function();
1232 }
1233
1234 key_equal const&
1235 key_eq() const
1236 {
1237 return m_config.key_eq();
1238 }
1239
1240 //--------------------------------------------------------------------------
1241 //
1242 // Comparison
1243 //
1244 //--------------------------------------------------------------------------
1245
1246 // This differs from the standard in that the comparison
1247 // is only done on the key portion of the value type, ignoring
1248 // the mapped type.
1249 //
1250 template <
1251 bool OtherIsMap,
1252 class OtherKey,
1253 class OtherT,
1254 class OtherDuration,
1255 class OtherHash,
1256 class OtherAllocator,
1257 bool maybe_multi = IsMulti>
1260 false,
1261 OtherIsMap,
1262 OtherKey,
1263 OtherT,
1264 OtherDuration,
1265 OtherHash,
1266 KeyEqual,
1267 OtherAllocator> const& other) const;
1268
1269 template <
1270 bool OtherIsMap,
1271 class OtherKey,
1272 class OtherT,
1273 class OtherDuration,
1274 class OtherHash,
1275 class OtherAllocator,
1276 bool maybe_multi = IsMulti>
1279 true,
1280 OtherIsMap,
1281 OtherKey,
1282 OtherT,
1283 OtherDuration,
1284 OtherHash,
1285 KeyEqual,
1286 OtherAllocator> const& other) const;
1287
1288 template <
1289 bool OtherIsMulti,
1290 bool OtherIsMap,
1291 class OtherKey,
1292 class OtherT,
1293 class OtherDuration,
1294 class OtherHash,
1295 class OtherAllocator>
1296 bool
1298 OtherIsMulti,
1299 OtherIsMap,
1300 OtherKey,
1301 OtherT,
1302 OtherDuration,
1303 OtherHash,
1304 KeyEqual,
1305 OtherAllocator> const& other) const
1306 {
1307 return !(this->operator==(other));
1308 }
1309
1310private:
1311 bool
1312 would_exceed(size_type additional) const
1313 {
1314 return size() + additional > bucket_count() * max_load_factor();
1315 }
1316
1317 void
1319 {
1320 if (would_exceed(additional))
1321 m_buck.resize(size() + additional, m_cont);
1322 XRPL_ASSERT(
1324 "beast::detail::aged_unordered_container::maybe_rehash : maximum "
1325 "load factor");
1326 }
1327
1328 // map, set
1329 template <bool maybe_multi = IsMulti>
1330 auto
1332
1333 // multimap, multiset
1334 template <bool maybe_multi = IsMulti>
1335 auto
1337
1338 template <class InputIt>
1339 void
1340 insert_unchecked(InputIt first, InputIt last)
1341 {
1342 for (; first != last; ++first)
1343 insert_unchecked(*first);
1344 }
1345
1346 template <class InputIt>
1347 void
1348 insert(InputIt first, InputIt last, std::input_iterator_tag)
1349 {
1350 for (; first != last; ++first)
1351 insert(*first);
1352 }
1353
1354 template <class InputIt>
1355 void
1356 insert(InputIt first, InputIt last, std::random_access_iterator_tag)
1357 {
1358 auto const n(std::distance(first, last));
1359 maybe_rehash(n);
1360 insert_unchecked(first, last);
1361 }
1362
1363 template <bool is_const, class Iterator>
1364 void
1366 {
1367 auto& e(*pos.iterator());
1368 e.when = now;
1369 chronological.list.erase(chronological.list.iterator_to(e));
1370 chronological.list.push_back(e);
1371 }
1372
1373 template <bool maybe_propagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
1376 {
1377 std::swap(m_config.key_compare(), other.m_config.key_compare());
1378 std::swap(m_config.alloc(), other.m_config.alloc());
1379 std::swap(m_config.clock, other.m_config.clock);
1380 }
1381
1382 template <bool maybe_propagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
1385 {
1386 std::swap(m_config.key_compare(), other.m_config.key_compare());
1387 std::swap(m_config.clock, other.m_config.clock);
1388 }
1389
1390private:
1394};
1395
1396//------------------------------------------------------------------------------
1397
1398template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1400 clock_type& clock)
1401 : m_config(clock), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1402{
1403}
1404
1405template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1407 clock_type& clock,
1408 Hash const& hash)
1409 : m_config(clock, hash), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1410{
1411}
1412
1413template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1415 clock_type& clock,
1416 KeyEqual const& key_eq)
1417 : m_config(clock, key_eq), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1418{
1419}
1420
1421template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1423 clock_type& clock,
1424 Allocator const& alloc)
1425 : m_config(clock, alloc)
1426 , m_buck(alloc)
1427 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1428{
1429}
1430
1431template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1433 clock_type& clock,
1434 Hash const& hash,
1435 KeyEqual const& key_eq)
1436 : m_config(clock, hash, key_eq)
1437 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1438{
1439}
1440
1441template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1443 clock_type& clock,
1444 Hash const& hash,
1445 Allocator const& alloc)
1446 : m_config(clock, hash, alloc)
1447 , m_buck(alloc)
1448 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1449{
1450}
1451
1452template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1454 clock_type& clock,
1455 KeyEqual const& key_eq,
1456 Allocator const& alloc)
1457 : m_config(clock, key_eq, alloc)
1458 , m_buck(alloc)
1459 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1460{
1461}
1462
1463template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1465 clock_type& clock,
1466 Hash const& hash,
1467 KeyEqual const& key_eq,
1468 Allocator const& alloc)
1469 : m_config(clock, hash, key_eq, alloc)
1470 , m_buck(alloc)
1471 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1472{
1473}
1474
1475template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1476template <class InputIt>
1478 InputIt first,
1479 InputIt last,
1480 clock_type& clock)
1481 : m_config(clock), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1482{
1483 insert(first, last);
1484}
1485
1486template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1487template <class InputIt>
1489 InputIt first,
1490 InputIt last,
1491 clock_type& clock,
1492 Hash const& hash)
1493 : m_config(clock, hash), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1494{
1495 insert(first, last);
1496}
1497
1498template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1499template <class InputIt>
1501 InputIt first,
1502 InputIt last,
1503 clock_type& clock,
1504 KeyEqual const& key_eq)
1505 : m_config(clock, key_eq), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1506{
1507 insert(first, last);
1508}
1509
1510template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1511template <class InputIt>
1513 InputIt first,
1514 InputIt last,
1515 clock_type& clock,
1516 Allocator const& alloc)
1517 : m_config(clock, alloc)
1518 , m_buck(alloc)
1519 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1520{
1521 insert(first, last);
1522}
1523
1524template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1525template <class InputIt>
1527 InputIt first,
1528 InputIt last,
1529 clock_type& clock,
1530 Hash const& hash,
1531 KeyEqual const& key_eq)
1532 : m_config(clock, hash, key_eq)
1533 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1534{
1535 insert(first, last);
1536}
1537
1538template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1539template <class InputIt>
1541 InputIt first,
1542 InputIt last,
1543 clock_type& clock,
1544 Hash const& hash,
1545 Allocator const& alloc)
1546 : m_config(clock, hash, alloc)
1547 , m_buck(alloc)
1548 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1549{
1550 insert(first, last);
1551}
1552
1553template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1554template <class InputIt>
1556 InputIt first,
1557 InputIt last,
1558 clock_type& clock,
1559 KeyEqual const& key_eq,
1560 Allocator const& alloc)
1561 : m_config(clock, key_eq, alloc)
1562 , m_buck(alloc)
1563 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1564{
1565 insert(first, last);
1566}
1567
1568template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1569template <class InputIt>
1571 InputIt first,
1572 InputIt last,
1573 clock_type& clock,
1574 Hash const& hash,
1575 KeyEqual const& key_eq,
1576 Allocator const& alloc)
1577 : m_config(clock, hash, key_eq, alloc)
1578 , m_buck(alloc)
1579 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1580{
1581 insert(first, last);
1582}
1583
1584template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1586 aged_unordered_container const& other)
1587 : m_config(other.m_config)
1588 , m_buck(m_config.alloc())
1589 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1590{
1591 insert(other.cbegin(), other.cend());
1592}
1593
1594template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1596 aged_unordered_container const& other,
1597 Allocator const& alloc)
1598 : m_config(other.m_config, alloc)
1599 , m_buck(alloc)
1600 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1601{
1602 insert(other.cbegin(), other.cend());
1603}
1604
1605template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1608 : m_config(std::move(other.m_config)), m_buck(std::move(other.m_buck)), m_cont(std::move(other.m_cont))
1609{
1610 chronological.list = std::move(other.chronological.list);
1611}
1612
1613template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1616 Allocator const& alloc)
1617 : m_config(std::move(other.m_config), alloc)
1618 , m_buck(alloc)
1619 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1620{
1621 insert(other.cbegin(), other.cend());
1622 other.clear();
1623}
1624
1625template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1628 clock_type& clock)
1629 : m_config(clock), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1630{
1631 insert(init.begin(), init.end());
1632}
1633
1634template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1637 clock_type& clock,
1638 Hash const& hash)
1639 : m_config(clock, hash), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1640{
1641 insert(init.begin(), init.end());
1642}
1643
1644template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1647 clock_type& clock,
1648 KeyEqual const& key_eq)
1649 : m_config(clock, key_eq), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1650{
1651 insert(init.begin(), init.end());
1652}
1653
1654template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1657 clock_type& clock,
1658 Allocator const& alloc)
1659 : m_config(clock, alloc)
1660 , m_buck(alloc)
1661 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1662{
1663 insert(init.begin(), init.end());
1664}
1665
1666template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1669 clock_type& clock,
1670 Hash const& hash,
1671 KeyEqual const& key_eq)
1672 : m_config(clock, hash, key_eq)
1673 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1674{
1675 insert(init.begin(), init.end());
1676}
1677
1678template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1681 clock_type& clock,
1682 Hash const& hash,
1683 Allocator const& alloc)
1684 : m_config(clock, hash, alloc)
1685 , m_buck(alloc)
1686 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1687{
1688 insert(init.begin(), init.end());
1689}
1690
1691template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1694 clock_type& clock,
1695 KeyEqual const& key_eq,
1696 Allocator const& alloc)
1697 : m_config(clock, key_eq, alloc)
1698 , m_buck(alloc)
1699 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1700{
1701 insert(init.begin(), init.end());
1702}
1703
1704template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1707 clock_type& clock,
1708 Hash const& hash,
1709 KeyEqual const& key_eq,
1710 Allocator const& alloc)
1711 : m_config(clock, hash, key_eq, alloc)
1712 , m_buck(alloc)
1713 , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))
1714{
1715 insert(init.begin(), init.end());
1716}
1717
1718template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1723
1724template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1725auto
1728{
1729 if (this != &other)
1730 {
1731 size_type const n(other.size());
1732 clear();
1733 m_config = other.m_config;
1734 m_buck = Buckets(m_config.alloc());
1735 maybe_rehash(n);
1736 insert_unchecked(other.begin(), other.end());
1737 }
1738 return *this;
1739}
1740
1741template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1742auto
1745{
1746 size_type const n(other.size());
1747 clear();
1748 m_config = std::move(other.m_config);
1749 m_buck = Buckets(m_config.alloc());
1750 maybe_rehash(n);
1751 insert_unchecked(other.begin(), other.end());
1752 other.clear();
1753 return *this;
1754}
1755
1756template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1757auto
1765
1766//------------------------------------------------------------------------------
1767
1768template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1769template <class K, bool maybe_multi, bool maybe_map, class>
1772{
1773 auto const iter(m_cont.find(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal())));
1774 if (iter == m_cont.end())
1775 throw std::out_of_range("key not found");
1776 return iter->value.second;
1777}
1778
1779template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1780template <class K, bool maybe_multi, bool maybe_map, class>
1783{
1784 auto const iter(m_cont.find(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal())));
1785 if (iter == m_cont.end())
1786 throw std::out_of_range("key not found");
1787 return iter->value.second;
1788}
1789
1790template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1791template <bool maybe_multi, bool maybe_map, class>
1794{
1795 maybe_rehash(1);
1796 typename cont_type::insert_commit_data d;
1797 auto const result(
1798 m_cont.insert_check(key, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d));
1799 if (result.second)
1800 {
1802 m_cont.insert_commit(*p, d);
1803 chronological.list.push_back(*p);
1804 return p->value.second;
1805 }
1806 return result.first->value.second;
1807}
1808
1809template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1810template <bool maybe_multi, bool maybe_map, class>
1813{
1814 maybe_rehash(1);
1815 typename cont_type::insert_commit_data d;
1816 auto const result(
1817 m_cont.insert_check(key, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d));
1818 if (result.second)
1819 {
1820 element* const p(
1822 m_cont.insert_commit(*p, d);
1823 chronological.list.push_back(*p);
1824 return p->value.second;
1825 }
1826 return result.first->value.second;
1827}
1828
1829//------------------------------------------------------------------------------
1830
1831template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1832void
1834{
1835 for (auto iter(chronological.list.begin()); iter != chronological.list.end();)
1836 unlink_and_delete_element(&*iter++);
1837 chronological.list.clear();
1838 m_cont.clear();
1839 m_buck.clear();
1840}
1841
1842// map, set
1843template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1844template <bool maybe_multi>
1845auto
1848{
1849 maybe_rehash(1);
1850 typename cont_type::insert_commit_data d;
1851 auto const result(m_cont.insert_check(
1852 extract(value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d));
1853 if (result.second)
1854 {
1855 element* const p(new_element(value));
1856 auto const iter(m_cont.insert_commit(*p, d));
1857 chronological.list.push_back(*p);
1858 return std::make_pair(iterator(iter), true);
1859 }
1860 return std::make_pair(iterator(result.first), false);
1861}
1862
1863// multimap, multiset
1864template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1865template <bool maybe_multi>
1866auto
1869{
1870 maybe_rehash(1);
1871 element* const p(new_element(value));
1872 chronological.list.push_back(*p);
1873 auto const iter(m_cont.insert(*p));
1874 return iterator(iter);
1875}
1876
1877// map, set
1878template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1879template <bool maybe_multi, bool maybe_map>
1880auto
1883{
1884 maybe_rehash(1);
1885 typename cont_type::insert_commit_data d;
1886 auto const result(m_cont.insert_check(
1887 extract(value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d));
1888 if (result.second)
1889 {
1890 element* const p(new_element(std::move(value)));
1891 auto const iter(m_cont.insert_commit(*p, d));
1892 chronological.list.push_back(*p);
1893 return std::make_pair(iterator(iter), true);
1894 }
1895 return std::make_pair(iterator(result.first), false);
1896}
1897
1898// multimap, multiset
1899template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1900template <bool maybe_multi, bool maybe_map>
1901auto
1904{
1905 maybe_rehash(1);
1906 element* const p(new_element(std::move(value)));
1907 chronological.list.push_back(*p);
1908 auto const iter(m_cont.insert(*p));
1909 return iterator(iter);
1910}
1911
1912#if 1 // Use insert() instead of insert_check() insert_commit()
1913// set, map
1914template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1915template <bool maybe_multi, class... Args>
1916auto
1919{
1920 maybe_rehash(1);
1921 // VFALCO NOTE Its unfortunate that we need to
1922 // construct element here
1923 element* const p(new_element(std::forward<Args>(args)...));
1924 auto const result(m_cont.insert(*p));
1925 if (result.second)
1926 {
1927 chronological.list.push_back(*p);
1928 return std::make_pair(iterator(result.first), true);
1929 }
1930 delete_element(p);
1931 return std::make_pair(iterator(result.first), false);
1932}
1933#else // As original, use insert_check() / insert_commit () pair.
1934// set, map
1935template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1936template <bool maybe_multi, class... Args>
1937auto
1940{
1941 maybe_rehash(1);
1942 // VFALCO NOTE Its unfortunate that we need to
1943 // construct element here
1944 element* const p(new_element(std::forward<Args>(args)...));
1945 typename cont_type::insert_commit_data d;
1946 auto const result(m_cont.insert_check(
1947 extract(p->value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d));
1948 if (result.second)
1949 {
1950 auto const iter(m_cont.insert_commit(*p, d));
1951 chronological.list.push_back(*p);
1952 return std::make_pair(iterator(iter), true);
1953 }
1954 delete_element(p);
1955 return std::make_pair(iterator(result.first), false);
1956}
1957#endif // 0
1958
1959// multiset, multimap
1960template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1961template <bool maybe_multi, class... Args>
1962auto
1965{
1966 maybe_rehash(1);
1967 element* const p(new_element(std::forward<Args>(args)...));
1968 chronological.list.push_back(*p);
1969 auto const iter(m_cont.insert(*p));
1970 return iterator(iter);
1971}
1972
1973// set, map
1974template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1975template <bool maybe_multi, class... Args>
1976auto
1978 const_iterator /*hint*/,
1979 Args&&... args) -> typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type
1980{
1981 maybe_rehash(1);
1982 // VFALCO NOTE Its unfortunate that we need to
1983 // construct element here
1984 element* const p(new_element(std::forward<Args>(args)...));
1985 typename cont_type::insert_commit_data d;
1986 auto const result(m_cont.insert_check(
1987 extract(p->value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d));
1988 if (result.second)
1989 {
1990 auto const iter(m_cont.insert_commit(*p, d));
1991 chronological.list.push_back(*p);
1992 return std::make_pair(iterator(iter), true);
1993 }
1994 delete_element(p);
1995 return std::make_pair(iterator(result.first), false);
1996}
1997
1998template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
1999template <bool is_const, class Iterator>
2007
2008template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2009template <bool is_const, class Iterator>
2020
2021template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2022template <class K>
2023auto
2025{
2026 auto iter(m_cont.find(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal())));
2027 if (iter == m_cont.end())
2028 return 0;
2029 size_type n(0);
2030 for (;;)
2031 {
2032 auto p(&*iter++);
2033 bool const done(m_config(*p, extract(iter->value)));
2034 unlink_and_delete_element(p);
2035 ++n;
2036 if (done)
2037 break;
2038 }
2039 return n;
2040}
2041
2042template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2043void
2045 aged_unordered_container& other) noexcept
2046{
2047 swap_data(other);
2048 std::swap(chronological, other.chronological);
2049 std::swap(m_cont, other.m_cont);
2050}
2051
2052template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2053template <class K>
2054auto
2056{
2057 auto const now(clock().now());
2058 size_type n(0);
2059 auto const range(equal_range(k));
2060 for (auto iter : range)
2061 {
2062 touch(iter, now);
2063 ++n;
2064 }
2065 return n;
2066}
2067
2068template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2069template <
2070 bool OtherIsMap,
2071 class OtherKey,
2072 class OtherT,
2073 class OtherDuration,
2074 class OtherHash,
2075 class OtherAllocator,
2076 bool maybe_multi>
2080 false,
2081 OtherIsMap,
2082 OtherKey,
2083 OtherT,
2084 OtherDuration,
2085 OtherHash,
2086 KeyEqual,
2087 OtherAllocator> const& other) const
2088{
2089 if (size() != other.size())
2090 return false;
2091 for (auto iter(cbegin()), last(cend()), otherLast(other.cend()); iter != last; ++iter)
2092 {
2093 auto otherIter(other.find(extract(*iter)));
2094 if (otherIter == otherLast)
2095 return false;
2096 }
2097 return true;
2098}
2099
2100template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2101template <
2102 bool OtherIsMap,
2103 class OtherKey,
2104 class OtherT,
2105 class OtherDuration,
2106 class OtherHash,
2107 class OtherAllocator,
2108 bool maybe_multi>
2112 true,
2113 OtherIsMap,
2114 OtherKey,
2115 OtherT,
2116 OtherDuration,
2117 OtherHash,
2118 KeyEqual,
2119 OtherAllocator> const& other) const
2120{
2121 if (size() != other.size())
2122 return false;
2123 for (auto iter(cbegin()), last(cend()); iter != last;)
2124 {
2125 auto const& k(extract(*iter));
2126 auto const eq(equal_range(k));
2127 auto const oeq(other.equal_range(k));
2128#if BEAST_NO_CXX14_IS_PERMUTATION
2129 if (std::distance(eq.first, eq.second) != std::distance(oeq.first, oeq.second) ||
2130 !std::is_permutation(eq.first, eq.second, oeq.first))
2131 return false;
2132#else
2133 if (!std::is_permutation(eq.first, eq.second, oeq.first, oeq.second))
2134 return false;
2135#endif
2136 iter = eq.second;
2137 }
2138 return true;
2139}
2140
2141//------------------------------------------------------------------------------
2142
2143// map, set
2144template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2145template <bool maybe_multi>
2146auto
2149{
2150 typename cont_type::insert_commit_data d;
2151 auto const result(m_cont.insert_check(
2152 extract(value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d));
2153 if (result.second)
2154 {
2155 element* const p(new_element(value));
2156 auto const iter(m_cont.insert_commit(*p, d));
2157 chronological.list.push_back(*p);
2158 return std::make_pair(iterator(iter), true);
2159 }
2160 return std::make_pair(iterator(result.first), false);
2161}
2162
2163// multimap, multiset
2164template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2165template <bool maybe_multi>
2166auto
2168 value_type const& value) -> typename std::enable_if<maybe_multi, iterator>::type
2169{
2170 element* const p(new_element(value));
2171 chronological.list.push_back(*p);
2172 auto const iter(m_cont.insert(*p));
2173 return iterator(iter);
2174}
2175
2176//------------------------------------------------------------------------------
2177
2178} // namespace detail
2179
2180//------------------------------------------------------------------------------
2181
2182template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2184 beast::detail::aged_unordered_container<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>> : std::true_type
2185{
2186 explicit is_aged_container() = default;
2187};
2188
2189// Free functions
2190
2191template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Hash, class KeyEqual, class Allocator>
2192void
2199
2201template <
2202 bool IsMulti,
2203 bool IsMap,
2204 class Key,
2205 class T,
2206 class Clock,
2207 class Hash,
2208 class KeyEqual,
2209 class Allocator,
2210 class Rep,
2211 class Period>
2215 std::chrono::duration<Rep, Period> const& age) noexcept
2216{
2217 std::size_t n(0);
2218 auto const expired(c.clock().now() - age);
2219 for (auto iter(c.chronological.cbegin()); iter != c.chronological.cend() && iter.when() <= expired;)
2220 {
2221 iter = c.erase(iter);
2222 ++n;
2223 }
2224 return n;
2225}
2226
2227} // namespace beast
T addressof(T... args)
T allocate(T... args)
T capacity(T... args)
T ceil(T... args)
Abstract interface to a clock.
typename Clock::time_point time_point
typename Clock::duration duration
bool operator()(element const &e, Key const &k) const
bool operator()(Key const &k, element const &e) const
bool operator()(element const &lhs, element const &rhs) const
const_iterator iterator_to(value_type const &value) const
beast::detail::aged_container_iterator< true, typename list_type::reverse_iterator > const_reverse_iterator
beast::detail::aged_container_iterator< true, typename list_type::iterator > const_iterator
beast::detail::aged_container_iterator<!IsMap, typename list_type::iterator > iterator
beast::detail::aged_container_iterator<!IsMap, typename list_type::reverse_iterator > reverse_iterator
config_t(config_t &&other, Allocator const &alloc)
config_t(clock_type &clock_, KeyEqual const &keyEqual)
config_t(clock_type &clock_, KeyEqual const &keyEqual, Allocator const &alloc_)
config_t(clock_type &clock_, Hash const &hash, Allocator const &alloc_)
config_t(clock_type &clock_, Allocator const &alloc_)
config_t(clock_type &clock_, Hash const &hash, KeyEqual const &keyEqual, Allocator const &alloc_)
config_t(config_t const &other, Allocator const &alloc)
config_t(clock_type &clock_, Hash const &hash, KeyEqual const &keyEqual)
Associative container where each element is also indexed by time.
beast::detail::aged_container_iterator< true, typename cont_type::iterator > const_iterator
aged_unordered_container(clock_type &clock, Hash const &hash, KeyEqual const &key_eq)
std::conditional< IsMap, T, void * >::type & at(K const &k)
aged_unordered_container(clock_type &clock, KeyEqual const &key_eq, Allocator const &alloc)
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock, Hash const &hash)
auto insert(value_type const &value) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
std::enable_if< maybe_map &&std::is_constructible< value_type, P && >::value, typenamestd::conditional< IsMulti, iterator, std::pair< iterator, bool > >::type >::type insert(P &&value)
typename std::allocator_traits< Allocator >::const_pointer const_pointer
aged_unordered_container(InputIt first, InputIt last, clock_type &clock, Hash const &hash, KeyEqual const &key_eq)
aged_unordered_container(InputIt first, InputIt last, clock_type &clock, Allocator const &alloc)
static Key const & extract(value_type const &value)
beast::detail::aged_container_iterator< false, Iterator > erase(beast::detail::aged_container_iterator< is_const, Iterator > first, beast::detail::aged_container_iterator< is_const, Iterator > last)
bool would_exceed(size_type additional) const
aged_unordered_container & operator=(aged_unordered_container const &other)
aged_unordered_container(clock_type &clock, KeyEqual const &key_eq)
std::enable_if< maybe_multi, iterator >::type insert(const_iterator, value_type const &value)
const_local_iterator begin(size_type n) const
void insert_unchecked(InputIt first, InputIt last)
aged_unordered_container(aged_unordered_container const &other)
const_local_iterator cend(size_type n) const
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock, KeyEqual const &key_eq, Allocator const &alloc)
aged_unordered_container(InputIt first, InputIt last, clock_type &clock, Hash const &hash)
const_local_iterator end(size_type n) const
typename std::allocator_traits< Allocator >::pointer pointer
std::enable_if<!maybe_multi, bool >::type operator==(aged_unordered_container< false, OtherIsMap, OtherKey, OtherT, OtherDuration, OtherHash, KeyEqual, OtherAllocator > const &other) const
void insert(std::initializer_list< value_type > init)
std::enable_if<!maybe_multi, iterator >::type insert(const_iterator, value_type const &value)
std::pair< iterator, iterator > equal_range(K const &k)
std::enable_if< maybe_multi, iterator >::type emplace_hint(const_iterator, Args &&... args)
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock)
aged_unordered_container(clock_type &clock, Hash const &hash, Allocator const &alloc)
typename std::allocator_traits< Allocator >::template rebind_alloc< element > BucketAllocator
typename std::conditional< IsMap, std::pair< Key const, T >, Key >::type value_type
auto insert_unchecked(value_type const &value) -> typename std::enable_if< maybe_multi, iterator >::type
const_iterator iterator_to(value_type const &value) const
std::enable_if<!maybe_propagate >::type swap_data(aged_unordered_container &other) noexcept
typename cont_type::bucket_traits bucket_traits
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock, Hash const &hash, KeyEqual const &key_eq, Allocator const &alloc)
auto insert(value_type &&value) -> typename std::enable_if< maybe_multi &&!maybe_map, iterator >::type
beast::detail::aged_container_iterator<!IsMap, typename cont_type::local_iterator > local_iterator
std::pair< const_iterator, const_iterator > equal_range(K const &k) const
void touch(beast::detail::aged_container_iterator< is_const, Iterator > pos)
std::conditional< IsMap, T, void * >::type & operator[](Key const &key)
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock, Allocator const &alloc)
std::enable_if<!maybe_multi, iterator >::type insert(const_iterator, value_type &&value)
auto emplace(Args &&... args) -> typename std::enable_if< maybe_multi, iterator >::type
std::enable_if< maybe_multi, bool >::type operator==(aged_unordered_container< true, OtherIsMap, OtherKey, OtherT, OtherDuration, OtherHash, KeyEqual, OtherAllocator > const &other) const
beast::detail::aged_container_iterator<!IsMap, typename cont_type::iterator > iterator
std::enable_if< maybe_multi, iterator >::type insert(const_iterator, value_type &&value)
aged_unordered_container(InputIt first, InputIt last, clock_type &clock, Hash const &hash, KeyEqual const &key_eq, Allocator const &alloc)
const_local_iterator cbegin(size_type n) const
auto insert_unchecked(value_type const &value) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
typename std::allocator_traits< Allocator >::template rebind_alloc< element > ElementAllocator
aged_unordered_container(aged_unordered_container const &other, Allocator const &alloc)
aged_unordered_container(clock_type &clock, Allocator const &alloc)
auto emplace_hint(const_iterator, Args &&... args) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
void touch(beast::detail::aged_container_iterator< is_const, Iterator > pos, typename clock_type::time_point const &now)
beast::detail::aged_container_iterator< false, Iterator > erase(beast::detail::aged_container_iterator< is_const, Iterator > pos)
void insert(InputIt first, InputIt last, std::input_iterator_tag)
aged_unordered_container & operator=(aged_unordered_container &&other)
std::enable_if< maybe_propagate >::type swap_data(aged_unordered_container &other) noexcept
aged_unordered_container & operator=(std::initializer_list< value_type > init)
aged_unordered_container(InputIt first, InputIt last, clock_type &clock, Hash const &hash, Allocator const &alloc)
bool operator!=(aged_unordered_container< OtherIsMulti, OtherIsMap, OtherKey, OtherT, OtherDuration, OtherHash, KeyEqual, OtherAllocator > const &other) const
void insert(InputIt first, InputIt last, std::random_access_iterator_tag)
typename std::conditional< IsMulti, typename boost::intrusive::make_unordered_multiset< element, boost::intrusive::constant_time_size< true >, boost::intrusive::hash< ValueHash >, boost::intrusive::equal< KeyValueEqual >, boost::intrusive::cache_begin< true > >::type, typename boost::intrusive::make_unordered_set< element, boost::intrusive::constant_time_size< true >, boost::intrusive::hash< ValueHash >, boost::intrusive::equal< KeyValueEqual >, boost::intrusive::cache_begin< true > >::type >::type cont_type
aged_unordered_container(clock_type &clock, Hash const &hash)
aged_unordered_container(clock_type &clock, Hash const &hash, KeyEqual const &key_eq, Allocator const &alloc)
auto emplace(Args &&... args) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
std::conditional< IsMap, T, void * >::type const & at(K const &k) const
typename boost::intrusive::make_list< element, boost::intrusive::constant_time_size< false > >::type list_type
void swap(aged_unordered_container &other) noexcept
aged_unordered_container(InputIt first, InputIt last, clock_type &clock)
aged_unordered_container(aged_unordered_container &&other)
std::enable_if< maybe_map &&std::is_constructible< value_type, P && >::value, typenamestd::conditional< IsMulti, iterator, std::pair< iterator, bool > >::type >::type insert(const_iterator hint, P &&value)
auto insert(value_type const &value) -> typename std::enable_if< maybe_multi, iterator >::type
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock, Hash const &hash, KeyEqual const &key_eq)
std::conditional< IsMap, T, void * >::type & operator[](Key &&key)
aged_unordered_container(InputIt first, InputIt last, clock_type &clock, KeyEqual const &key_eq, Allocator const &alloc)
aged_unordered_container(InputIt first, InputIt last, clock_type &clock, KeyEqual const &key_eq)
class beast::detail::aged_unordered_container::chronological_t chronological
beast::detail::aged_container_iterator< true, typename cont_type::local_iterator > const_local_iterator
auto insert(value_type &&value) -> typename std::enable_if<!maybe_multi &&!maybe_map, std::pair< iterator, bool > >::type
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock, KeyEqual const &key_eq)
aged_unordered_container(aged_unordered_container &&other, Allocator const &alloc)
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock, Hash const &hash, Allocator const &alloc)
T clear(T... args)
T construct(T... args)
T deallocate(T... args)
T destroy(T... args)
T distance(T... args)
T forward_as_tuple(T... args)
T get_allocator(T... args)
T is_permutation(T... args)
T is_same_v
T make_pair(T... args)
T max(T... args)
T max_size(T... args)
std::enable_if< is_aged_container< AgedContainer >::value, std::size_t >::type expire(AgedContainer &c, std::chrono::duration< Rep, Period > const &age)
Expire aged container items past the specified age.
void swap(beast::detail::aged_ordered_container< IsMulti, IsMap, Key, T, Clock, Compare, Allocator > &lhs, beast::detail::aged_ordered_container< IsMulti, IsMap, Key, T, Clock, Compare, Allocator > &rhs) noexcept
STL namespace.
T piecewise_construct
T cref(T... args)
T release(T... args)
T resize(T... args)
T size(T... args)
typename aged_unordered_container::value_type value_type
typename aged_unordered_container::time_point time_point
element(time_point const &when_, value_type const &value_)
element(time_point const &when_, value_type &&value_)
element(time_point const &when_, Args &&... args)
T swap(T... args)