rippled
Loading...
Searching...
No Matches
aged_unordered_container.h
1#ifndef BEAST_CONTAINER_DETAIL_AGED_UNORDERED_CONTAINER_H_INCLUDED
2#define BEAST_CONTAINER_DETAIL_AGED_UNORDERED_CONTAINER_H_INCLUDED
3
4#include <xrpl/beast/clock/abstract_clock.h>
5#include <xrpl/beast/container/aged_container.h>
6#include <xrpl/beast/container/detail/aged_associative_container.h>
7#include <xrpl/beast/container/detail/aged_container_iterator.h>
8#include <xrpl/beast/container/detail/empty_base_optimization.h>
9
10#include <boost/intrusive/list.hpp>
11#include <boost/intrusive/unordered_set.hpp>
12
13#include <algorithm>
14#include <cmath>
15#include <functional>
16#include <initializer_list>
17#include <iterator>
18#include <memory>
19#include <type_traits>
20#include <utility>
21
22/*
23
24TODO
25
26- Add constructor variations that take a bucket count
27
28- Review for noexcept and exception guarantees
29
30- Call the safe version of is_permutation that takes 4 iterators
31
32*/
33
34#ifndef BEAST_NO_CXX14_IS_PERMUTATION
35#define BEAST_NO_CXX14_IS_PERMUTATION 1
36#endif
37
38namespace beast {
39namespace detail {
40
58template <
59 bool IsMulti,
60 bool IsMap,
61 class Key,
62 class T,
63 class Clock = std::chrono::steady_clock,
64 class Hash = std::hash<Key>,
65 class KeyEqual = std::equal_to<Key>,
66 class Allocator = std::allocator<
69{
70public:
74 using key_type = Key;
75 using mapped_type = T;
76 using value_type =
80
81 // Introspection (for unit tests)
85
86private:
87 static Key const&
88 extract(value_type const& value)
89 {
91 }
92
93 // VFALCO TODO hoist to remove template argument dependencies
94 struct element
95 : boost::intrusive::unordered_set_base_hook<
96 boost::intrusive::link_mode<boost::intrusive::normal_link>>,
97 boost::intrusive::list_base_hook<
98 boost::intrusive::link_mode<boost::intrusive::normal_link>>
99 {
100 // Stash types here so the iterator doesn't
101 // need to see the container declaration.
102 struct stashed
103 {
104 explicit stashed() = default;
105
108 };
109
110 element(time_point const& when_, value_type const& value_)
111 : value(value_), when(when_)
112 {
113 }
114
115 element(time_point const& when_, value_type&& value_)
116 : value(std::move(value_)), when(when_)
117 {
118 }
119
120 template <
121 class... Args,
122 class = typename std::enable_if<
124 element(time_point const& when_, Args&&... args)
125 : value(std::forward<Args>(args)...), when(when_)
126 {
127 }
128
131 };
132
133 // VFALCO TODO hoist to remove template argument dependencies
134 class ValueHash : public Hash
135 {
136 public:
138 using result_type = size_t;
139
141 {
142 }
143
144 ValueHash(Hash const& h) : Hash(h)
145 {
146 }
147
149 operator()(element const& e) const
150 {
151 return Hash::operator()(extract(e.value));
152 }
153
154 Hash&
156 {
157 return *this;
158 }
159
160 Hash const&
162 {
163 return *this;
164 }
165 };
166
167 // Compares value_type against element, used in find/insert_check
168 // VFALCO TODO hoist to remove template argument dependencies
169 class KeyValueEqual : public KeyEqual
170 {
171 public:
174 using result_type = bool;
175
177 {
178 }
179
180 KeyValueEqual(KeyEqual const& keyEqual) : KeyEqual(keyEqual)
181 {
182 }
183
184 bool
185 operator()(Key const& k, element const& e) const
186 {
187 return KeyEqual::operator()(k, extract(e.value));
188 }
189
190 bool
191 operator()(element const& e, Key const& k) const
192 {
193 return KeyEqual::operator()(extract(e.value), k);
194 }
195
196 bool
197 operator()(element const& lhs, element const& rhs) const
198 {
199 return KeyEqual::operator()(extract(lhs.value), extract(rhs.value));
200 }
201
202 KeyEqual&
204 {
205 return *this;
206 }
207
208 KeyEqual const&
209 key_eq() const
210 {
211 return *this;
212 }
213 };
214
215 using list_type = typename boost::intrusive::
216 make_list<element, boost::intrusive::constant_time_size<false>>::type;
217
218 using cont_type = typename std::conditional<
219 IsMulti,
220 typename boost::intrusive::make_unordered_multiset<
221 element,
222 boost::intrusive::constant_time_size<true>,
223 boost::intrusive::hash<ValueHash>,
224 boost::intrusive::equal<KeyValueEqual>,
225 boost::intrusive::cache_begin<true>>::type,
226 typename boost::intrusive::make_unordered_set<
227 element,
228 boost::intrusive::constant_time_size<true>,
229 boost::intrusive::hash<ValueHash>,
230 boost::intrusive::equal<KeyValueEqual>,
231 boost::intrusive::cache_begin<true>>::type>::type;
232
233 using bucket_type = typename cont_type::bucket_type;
234 using bucket_traits = typename cont_type::bucket_traits;
235
237 Allocator>::template rebind_alloc<element>;
238
240
242 Allocator>::template rebind_alloc<element>;
243
245
247 : private ValueHash,
248 private KeyValueEqual,
249 private beast::detail::empty_base_optimization<ElementAllocator>
250 {
251 public:
252 explicit config_t(clock_type& clock_) : clock(clock_)
253 {
254 }
255
256 config_t(clock_type& clock_, Hash const& hash)
257 : ValueHash(hash), clock(clock_)
258 {
259 }
260
261 config_t(clock_type& clock_, KeyEqual const& keyEqual)
262 : KeyValueEqual(keyEqual), clock(clock_)
263 {
264 }
265
266 config_t(clock_type& clock_, Allocator const& alloc_)
268 , clock(clock_)
269 {
270 }
271
272 config_t(clock_type& clock_, Hash const& hash, KeyEqual const& keyEqual)
273 : ValueHash(hash), KeyValueEqual(keyEqual), clock(clock_)
274 {
275 }
276
277 config_t(clock_type& clock_, Hash const& hash, Allocator const& alloc_)
278 : ValueHash(hash)
280 , clock(clock_)
281 {
282 }
283
285 clock_type& clock_,
286 KeyEqual const& keyEqual,
287 Allocator const& alloc_)
288 : KeyValueEqual(keyEqual)
290 , clock(clock_)
291 {
292 }
293
295 clock_type& clock_,
296 Hash const& hash,
297 KeyEqual const& keyEqual,
298 Allocator const& alloc_)
299 : ValueHash(hash)
300 , KeyValueEqual(keyEqual)
302 , clock(clock_)
303 {
304 }
305
306 config_t(config_t const& other)
307 : ValueHash(other.hash_function())
308 , KeyValueEqual(other.key_eq())
310 ElementAllocatorTraits::select_on_container_copy_construction(
311 other.alloc()))
312 , clock(other.clock)
313 {
314 }
315
316 config_t(config_t const& other, Allocator const& alloc)
317 : ValueHash(other.hash_function())
318 , KeyValueEqual(other.key_eq())
320 , clock(other.clock)
321 {
322 }
323
325 : ValueHash(std::move(other.hash_function()))
326 , KeyValueEqual(std::move(other.key_eq()))
328 std::move(other.alloc()))
329 , clock(other.clock)
330 {
331 }
332
333 config_t(config_t&& other, Allocator const& alloc)
334 : ValueHash(std::move(other.hash_function()))
335 , KeyValueEqual(std::move(other.key_eq()))
337 , clock(other.clock)
338 {
339 }
340
341 config_t&
342 operator=(config_t const& other)
343 {
344 hash_function() = other.hash_function();
345 key_eq() = other.key_eq();
346 alloc() = other.alloc();
347 clock = other.clock;
348 return *this;
349 }
350
351 config_t&
353 {
354 hash_function() = std::move(other.hash_function());
355 key_eq() = std::move(other.key_eq());
356 alloc() = std::move(other.alloc());
357 clock = other.clock;
358 return *this;
359 }
360
361 ValueHash&
363 {
364 return *this;
365 }
366
367 ValueHash const&
369 {
370 return *this;
371 }
372
373 Hash&
375 {
377 }
378
379 Hash const&
381 {
383 }
384
387 {
388 return *this;
389 }
390
391 KeyValueEqual const&
393 {
394 return *this;
395 }
396
397 KeyEqual&
399 {
400 return key_value_equal().key_eq();
401 }
402
403 KeyEqual const&
404 key_eq() const
405 {
406 return key_value_equal().key_eq();
407 }
408
415
416 ElementAllocator const&
422
424 };
425
427 {
428 public:
431 typename std::allocator_traits<Allocator>::template rebind_alloc<
432 bucket_type>>;
433
435 {
436 m_vec.resize(cont_type::suggested_upper_bucket_count(0));
437 }
438
439 Buckets(Allocator const& alloc) : m_max_load_factor(1.f), m_vec(alloc)
440 {
441 m_vec.resize(cont_type::suggested_upper_bucket_count(0));
442 }
443
444 operator bucket_traits()
445 {
446 return bucket_traits(&m_vec[0], m_vec.size());
447 }
448
449 void
451 {
452 m_vec.clear();
453 }
454
457 {
458 return m_vec.max_size();
459 }
460
461 float&
463 {
464 return m_max_load_factor;
465 }
466
467 float const&
469 {
470 return m_max_load_factor;
471 }
472
473 // count is the number of buckets
474 template <class Container>
475 void
476 rehash(size_type count, Container& c)
477 {
478 size_type const size(m_vec.size());
479 if (count == size)
480 return;
481 if (count > m_vec.capacity())
482 {
483 // Need two vectors otherwise we
484 // will destroy non-empty buckets.
486 std::swap(m_vec, vec);
488 c.rehash(bucket_traits(&m_vec[0], m_vec.size()));
489 return;
490 }
491 // Rehash in place.
492 if (count > size)
493 {
494 // This should not reallocate since
495 // we checked capacity earlier.
497 c.rehash(bucket_traits(&m_vec[0], count));
498 return;
499 }
500 // Resize must happen after rehash otherwise
501 // we might destroy non-empty buckets.
502 c.rehash(bucket_traits(&m_vec[0], count));
504 }
505
506 // Resize the buckets to accommodate at least n items.
507 template <class Container>
508 void
509 resize(size_type n, Container& c)
510 {
511 size_type const suggested(
512 cont_type::suggested_upper_bucket_count(n));
513 rehash(suggested, c);
514 }
515
516 private:
519 };
520
521 template <class... Args>
522 element*
523 new_element(Args&&... args)
524 {
525 struct Deleter
526 {
528 Deleter(ElementAllocator& a) : a_(a)
529 {
530 }
531
532 void
533 operator()(element* p)
534 {
535 ElementAllocatorTraits::deallocate(a_.get(), p, 1);
536 }
537 };
538
541 Deleter(m_config.alloc()));
543 m_config.alloc(),
544 p.get(),
545 clock().now(),
546 std::forward<Args>(args)...);
547 return p.release();
548 }
549
550 void
557
558 void
560 {
561 chronological.list.erase(chronological.list.iterator_to(*p));
562 m_cont.erase(m_cont.iterator_to(*p));
564 }
565
566public:
567 using hasher = Hash;
568 using key_equal = KeyEqual;
569 using allocator_type = Allocator;
575
576 // A set iterator (IsMap==false) is always const
577 // because the elements of a set are immutable.
578 using iterator = beast::detail::
579 aged_container_iterator<!IsMap, typename cont_type::iterator>;
580 using const_iterator = beast::detail::
581 aged_container_iterator<true, typename cont_type::iterator>;
582
583 using local_iterator = beast::detail::
584 aged_container_iterator<!IsMap, typename cont_type::local_iterator>;
585 using const_local_iterator = beast::detail::
586 aged_container_iterator<true, typename cont_type::local_iterator>;
587
588 //--------------------------------------------------------------------------
589 //
590 // Chronological ordered iterators
591 //
592 // "Memberspace"
593 // http://accu.org/index.php/journals/1527
594 //
595 //--------------------------------------------------------------------------
596
598 {
599 public:
600 // A set iterator (IsMap==false) is always const
601 // because the elements of a set are immutable.
602 using iterator = beast::detail::
603 aged_container_iterator<!IsMap, typename list_type::iterator>;
604 using const_iterator = beast::detail::
605 aged_container_iterator<true, typename list_type::iterator>;
607 !IsMap,
608 typename list_type::reverse_iterator>;
609 using const_reverse_iterator = beast::detail::
610 aged_container_iterator<true, typename list_type::reverse_iterator>;
611
614 {
615 return iterator(list.begin());
616 }
617
619 begin() const
620 {
621 return const_iterator(list.begin());
622 }
623
625 cbegin() const
626 {
627 return const_iterator(list.begin());
628 }
629
632 {
633 return iterator(list.end());
634 }
635
637 end() const
638 {
639 return const_iterator(list.end());
640 }
641
643 cend() const
644 {
645 return const_iterator(list.end());
646 }
647
650 {
651 return reverse_iterator(list.rbegin());
652 }
653
655 rbegin() const
656 {
657 return const_reverse_iterator(list.rbegin());
658 }
659
661 crbegin() const
662 {
663 return const_reverse_iterator(list.rbegin());
664 }
665
668 {
669 return reverse_iterator(list.rend());
670 }
671
673 rend() const
674 {
675 return const_reverse_iterator(list.rend());
676 }
677
679 crend() const
680 {
681 return const_reverse_iterator(list.rend());
682 }
683
686 {
687 static_assert(
689 "must be standard layout");
690 return list.iterator_to(*reinterpret_cast<element*>(
691 reinterpret_cast<uint8_t*>(&value) -
692 ((std::size_t)std::addressof(((element*)0)->member))));
693 }
694
696 iterator_to(value_type const& value) const
697 {
698 static_assert(
700 "must be standard layout");
701 return list.iterator_to(*reinterpret_cast<element const*>(
702 reinterpret_cast<uint8_t const*>(&value) -
703 ((std::size_t)std::addressof(((element*)0)->member))));
704 }
705
706 private:
708 {
709 }
710
713
717
718 //--------------------------------------------------------------------------
719 //
720 // Construction
721 //
722 //--------------------------------------------------------------------------
723
725
727
729
731
732 aged_unordered_container(clock_type& clock, Allocator const& alloc);
733
736 Hash const& hash,
737 KeyEqual const& key_eq);
738
741 Hash const& hash,
742 Allocator const& alloc);
743
746 KeyEqual const& key_eq,
747 Allocator const& alloc);
748
751 Hash const& hash,
752 KeyEqual const& key_eq,
753 Allocator const& alloc);
754
755 template <class InputIt>
756 aged_unordered_container(InputIt first, InputIt last, clock_type& clock);
757
758 template <class InputIt>
760 InputIt first,
761 InputIt last,
763 Hash const& hash);
764
765 template <class InputIt>
767 InputIt first,
768 InputIt last,
770 KeyEqual const& key_eq);
771
772 template <class InputIt>
774 InputIt first,
775 InputIt last,
777 Allocator const& alloc);
778
779 template <class InputIt>
781 InputIt first,
782 InputIt last,
784 Hash const& hash,
785 KeyEqual const& key_eq);
786
787 template <class InputIt>
789 InputIt first,
790 InputIt last,
792 Hash const& hash,
793 Allocator const& alloc);
794
795 template <class InputIt>
797 InputIt first,
798 InputIt last,
800 KeyEqual const& key_eq,
801 Allocator const& alloc);
802
803 template <class InputIt>
805 InputIt first,
806 InputIt last,
808 Hash const& hash,
809 KeyEqual const& key_eq,
810 Allocator const& alloc);
811
813
815 aged_unordered_container const& other,
816 Allocator const& alloc);
817
819
822 Allocator const& alloc);
823
827
831 Hash const& hash);
832
836 KeyEqual const& key_eq);
837
841 Allocator const& alloc);
842
846 Hash const& hash,
847 KeyEqual const& key_eq);
848
852 Hash const& hash,
853 Allocator const& alloc);
854
858 KeyEqual const& key_eq,
859 Allocator const& alloc);
860
864 Hash const& hash,
865 KeyEqual const& key_eq,
866 Allocator const& alloc);
867
869
872
875
878
881 {
882 return m_config.alloc();
883 }
884
887 {
888 return m_config.clock;
889 }
890
891 clock_type const&
892 clock() const
893 {
894 return m_config.clock;
895 }
896
897 //--------------------------------------------------------------------------
898 //
899 // Element access (maps)
900 //
901 //--------------------------------------------------------------------------
902
903 template <
904 class K,
905 bool maybe_multi = IsMulti,
906 bool maybe_map = IsMap,
909 at(K const& k);
910
911 template <
912 class K,
913 bool maybe_multi = IsMulti,
914 bool maybe_map = IsMap,
917 at(K const& k) const;
918
919 template <
920 bool maybe_multi = IsMulti,
921 bool maybe_map = IsMap,
924 operator[](Key const& key);
925
926 template <
927 bool maybe_multi = IsMulti,
928 bool maybe_map = IsMap,
931 operator[](Key&& key);
932
933 //--------------------------------------------------------------------------
934 //
935 // Iterators
936 //
937 //--------------------------------------------------------------------------
938
941 {
942 return iterator(m_cont.begin());
943 }
944
946 begin() const
947 {
948 return const_iterator(m_cont.begin());
949 }
950
952 cbegin() const
953 {
954 return const_iterator(m_cont.begin());
955 }
956
959 {
960 return iterator(m_cont.end());
961 }
962
964 end() const
965 {
966 return const_iterator(m_cont.end());
967 }
968
970 cend() const
971 {
972 return const_iterator(m_cont.end());
973 }
974
977 {
978 static_assert(
979 std::is_standard_layout<element>::value, "must be standard layout");
980 return m_cont.iterator_to(*reinterpret_cast<element*>(
981 reinterpret_cast<uint8_t*>(&value) -
982 ((std::size_t)std::addressof(((element*)0)->member))));
983 }
984
986 iterator_to(value_type const& value) const
987 {
988 static_assert(
989 std::is_standard_layout<element>::value, "must be standard layout");
990 return m_cont.iterator_to(*reinterpret_cast<element const*>(
991 reinterpret_cast<uint8_t const*>(&value) -
992 ((std::size_t)std::addressof(((element*)0)->member))));
993 }
994
995 //--------------------------------------------------------------------------
996 //
997 // Capacity
998 //
999 //--------------------------------------------------------------------------
1000
1001 bool
1002 empty() const noexcept
1003 {
1004 return m_cont.empty();
1005 }
1006
1007 size_type
1008 size() const noexcept
1009 {
1010 return m_cont.size();
1011 }
1012
1013 size_type
1014 max_size() const noexcept
1015 {
1016 return m_config.max_size();
1017 }
1018
1019 //--------------------------------------------------------------------------
1020 //
1021 // Modifiers
1022 //
1023 //--------------------------------------------------------------------------
1024
1025 void
1027
1028 // map, set
1029 template <bool maybe_multi = IsMulti>
1030 auto
1031 insert(value_type const& value) ->
1033
1034 // multimap, multiset
1035 template <bool maybe_multi = IsMulti>
1036 auto
1037 insert(value_type const& value) ->
1039
1040 // map, set
1041 template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
1042 auto
1043 insert(value_type&& value) -> typename std::enable_if<
1044 !maybe_multi && !maybe_map,
1046
1047 // multimap, multiset
1048 template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
1049 auto
1050 insert(value_type&& value) ->
1052
1053 // map, set
1054 template <bool maybe_multi = IsMulti>
1056 insert(const_iterator /*hint*/, value_type const& value)
1057 {
1058 // Hint is ignored but we provide the interface so
1059 // callers may use ordered and unordered interchangeably.
1060 return insert(value).first;
1061 }
1062
1063 // multimap, multiset
1064 template <bool maybe_multi = IsMulti>
1066 insert(const_iterator /*hint*/, value_type const& value)
1067 {
1068 // VFALCO TODO The hint could be used to let
1069 // the client order equal ranges
1070 return insert(value);
1071 }
1072
1073 // map, set
1074 template <bool maybe_multi = IsMulti>
1077 {
1078 // Hint is ignored but we provide the interface so
1079 // callers may use ordered and unordered interchangeably.
1080 return insert(std::move(value)).first;
1081 }
1082
1083 // multimap, multiset
1084 template <bool maybe_multi = IsMulti>
1087 {
1088 // VFALCO TODO The hint could be used to let
1089 // the client order equal ranges
1090 return insert(std::move(value));
1091 }
1092
1093 // map, multimap
1094 template <class P, bool maybe_map = IsMap>
1095 typename std::enable_if<
1097 typename std::
1099 type
1100 insert(P&& value)
1101 {
1102 return emplace(std::forward<P>(value));
1103 }
1104
1105 // map, multimap
1106 template <class P, bool maybe_map = IsMap>
1107 typename std::enable_if<
1109 typename std::
1111 type
1112 insert(const_iterator hint, P&& value)
1113 {
1114 return emplace_hint(hint, std::forward<P>(value));
1115 }
1116
1117 template <class InputIt>
1118 void
1119 insert(InputIt first, InputIt last)
1120 {
1121 insert(
1122 first,
1123 last,
1125 }
1126
1127 void
1129 {
1130 insert(init.begin(), init.end());
1131 }
1132
1133 // set, map
1134 template <bool maybe_multi = IsMulti, class... Args>
1135 auto
1136 emplace(Args&&... args) ->
1138
1139 // multiset, multimap
1140 template <bool maybe_multi = IsMulti, class... Args>
1141 auto
1142 emplace(Args&&... args) ->
1144
1145 // set, map
1146 template <bool maybe_multi = IsMulti, class... Args>
1147 auto
1148 emplace_hint(const_iterator /*hint*/, Args&&... args) ->
1150
1151 // multiset, multimap
1152 template <bool maybe_multi = IsMulti, class... Args>
1154 emplace_hint(const_iterator /*hint*/, Args&&... args)
1155 {
1156 // VFALCO TODO The hint could be used for multi, to let
1157 // the client order equal ranges
1158 return emplace<maybe_multi>(std::forward<Args>(args)...);
1159 }
1160
1161 template <bool is_const, class Iterator>
1164
1165 template <bool is_const, class Iterator>
1170
1171 template <class K>
1172 auto
1173 erase(K const& k) -> size_type;
1174
1175 void
1177
1178 template <bool is_const, class Iterator>
1179 void
1184
1185 template <class K>
1186 auto
1187 touch(K const& k) -> size_type;
1188
1189 //--------------------------------------------------------------------------
1190 //
1191 // Lookup
1192 //
1193 //--------------------------------------------------------------------------
1194
1195 // VFALCO TODO Respect is_transparent (c++14)
1196 template <class K>
1197 size_type
1198 count(K const& k) const
1199 {
1200 return m_cont.count(
1201 k,
1204 }
1205
1206 // VFALCO TODO Respect is_transparent (c++14)
1207 template <class K>
1208 iterator
1209 find(K const& k)
1210 {
1211 return iterator(m_cont.find(
1212 k,
1215 }
1216
1217 // VFALCO TODO Respect is_transparent (c++14)
1218 template <class K>
1220 find(K const& k) const
1221 {
1222 return const_iterator(m_cont.find(
1223 k,
1226 }
1227
1228 // VFALCO TODO Respect is_transparent (c++14)
1229 template <class K>
1231 equal_range(K const& k)
1232 {
1233 auto const r(m_cont.equal_range(
1234 k,
1237 return std::make_pair(iterator(r.first), iterator(r.second));
1238 }
1239
1240 // VFALCO TODO Respect is_transparent (c++14)
1241 template <class K>
1243 equal_range(K const& k) const
1244 {
1245 auto const r(m_cont.equal_range(
1246 k,
1249 return std::make_pair(
1250 const_iterator(r.first), const_iterator(r.second));
1251 }
1252
1253 //--------------------------------------------------------------------------
1254 //
1255 // Bucket interface
1256 //
1257 //--------------------------------------------------------------------------
1258
1261 {
1262 return local_iterator(m_cont.begin(n));
1263 }
1264
1267 {
1268 return const_local_iterator(m_cont.begin(n));
1269 }
1270
1273 {
1274 return const_local_iterator(m_cont.begin(n));
1275 }
1276
1279 {
1280 return local_iterator(m_cont.end(n));
1281 }
1282
1285 {
1286 return const_local_iterator(m_cont.end(n));
1287 }
1288
1291 {
1292 return const_local_iterator(m_cont.end(n));
1293 }
1294
1295 size_type
1297 {
1298 return m_cont.bucket_count();
1299 }
1300
1301 size_type
1303 {
1304 return m_buck.max_bucket_count();
1305 }
1306
1307 size_type
1309 {
1310 return m_cont.bucket_size(n);
1311 }
1312
1313 size_type
1314 bucket(Key const& k) const
1315 {
1316 XRPL_ASSERT(
1317 bucket_count() != 0,
1318 "beast::detail::aged_unordered_container::bucket : nonzero bucket "
1319 "count");
1320 return m_cont.bucket(k, std::cref(m_config.hash_function()));
1321 }
1322
1323 //--------------------------------------------------------------------------
1324 //
1325 // Hash policy
1326 //
1327 //--------------------------------------------------------------------------
1328
1329 float
1331 {
1332 return size() / static_cast<float>(m_cont.bucket_count());
1333 }
1334
1335 float
1337 {
1338 return m_buck.max_load_factor();
1339 }
1340
1341 void
1343 {
1345 }
1346
1347 void
1353
1354 void
1359
1360 //--------------------------------------------------------------------------
1361 //
1362 // Observers
1363 //
1364 //--------------------------------------------------------------------------
1365
1366 hasher const&
1368 {
1369 return m_config.hash_function();
1370 }
1371
1372 key_equal const&
1373 key_eq() const
1374 {
1375 return m_config.key_eq();
1376 }
1377
1378 //--------------------------------------------------------------------------
1379 //
1380 // Comparison
1381 //
1382 //--------------------------------------------------------------------------
1383
1384 // This differs from the standard in that the comparison
1385 // is only done on the key portion of the value type, ignoring
1386 // the mapped type.
1387 //
1388 template <
1389 bool OtherIsMap,
1390 class OtherKey,
1391 class OtherT,
1392 class OtherDuration,
1393 class OtherHash,
1394 class OtherAllocator,
1395 bool maybe_multi = IsMulti>
1398 false,
1399 OtherIsMap,
1400 OtherKey,
1401 OtherT,
1402 OtherDuration,
1403 OtherHash,
1404 KeyEqual,
1405 OtherAllocator> const& other) const;
1406
1407 template <
1408 bool OtherIsMap,
1409 class OtherKey,
1410 class OtherT,
1411 class OtherDuration,
1412 class OtherHash,
1413 class OtherAllocator,
1414 bool maybe_multi = IsMulti>
1417 true,
1418 OtherIsMap,
1419 OtherKey,
1420 OtherT,
1421 OtherDuration,
1422 OtherHash,
1423 KeyEqual,
1424 OtherAllocator> const& other) const;
1425
1426 template <
1427 bool OtherIsMulti,
1428 bool OtherIsMap,
1429 class OtherKey,
1430 class OtherT,
1431 class OtherDuration,
1432 class OtherHash,
1433 class OtherAllocator>
1434 bool
1436 OtherIsMulti,
1437 OtherIsMap,
1438 OtherKey,
1439 OtherT,
1440 OtherDuration,
1441 OtherHash,
1442 KeyEqual,
1443 OtherAllocator> const& other) const
1444 {
1445 return !(this->operator==(other));
1446 }
1447
1448private:
1449 bool
1450 would_exceed(size_type additional) const
1451 {
1452 return size() + additional > bucket_count() * max_load_factor();
1453 }
1454
1455 void
1457 {
1458 if (would_exceed(additional))
1459 m_buck.resize(size() + additional, m_cont);
1460 XRPL_ASSERT(
1462 "beast::detail::aged_unordered_container::maybe_rehash : maximum "
1463 "load factor");
1464 }
1465
1466 // map, set
1467 template <bool maybe_multi = IsMulti>
1468 auto
1471
1472 // multimap, multiset
1473 template <bool maybe_multi = IsMulti>
1474 auto
1477
1478 template <class InputIt>
1479 void
1480 insert_unchecked(InputIt first, InputIt last)
1481 {
1482 for (; first != last; ++first)
1483 insert_unchecked(*first);
1484 }
1485
1486 template <class InputIt>
1487 void
1488 insert(InputIt first, InputIt last, std::input_iterator_tag)
1489 {
1490 for (; first != last; ++first)
1491 insert(*first);
1492 }
1493
1494 template <class InputIt>
1495 void
1496 insert(InputIt first, InputIt last, std::random_access_iterator_tag)
1497 {
1498 auto const n(std::distance(first, last));
1499 maybe_rehash(n);
1500 insert_unchecked(first, last);
1501 }
1502
1503 template <bool is_const, class Iterator>
1504 void
1507 typename clock_type::time_point const& now)
1508 {
1509 auto& e(*pos.iterator());
1510 e.when = now;
1511 chronological.list.erase(chronological.list.iterator_to(e));
1512 chronological.list.push_back(e);
1513 }
1514
1515 template <
1516 bool maybe_propagate = std::allocator_traits<
1517 Allocator>::propagate_on_container_swap::value>
1520 {
1521 std::swap(m_config.key_compare(), other.m_config.key_compare());
1522 std::swap(m_config.alloc(), other.m_config.alloc());
1523 std::swap(m_config.clock, other.m_config.clock);
1524 }
1525
1526 template <
1527 bool maybe_propagate = std::allocator_traits<
1528 Allocator>::propagate_on_container_swap::value>
1531 {
1532 std::swap(m_config.key_compare(), other.m_config.key_compare());
1533 std::swap(m_config.clock, other.m_config.clock);
1534 }
1535
1536private:
1540};
1541
1542//------------------------------------------------------------------------------
1543
1544template <
1545 bool IsMulti,
1546 bool IsMap,
1547 class Key,
1548 class T,
1549 class Clock,
1550 class Hash,
1551 class KeyEqual,
1552 class Allocator>
1554 IsMulti,
1555 IsMap,
1556 Key,
1557 T,
1558 Clock,
1559 Hash,
1560 KeyEqual,
1561 Allocator>::aged_unordered_container(clock_type& clock)
1562 : m_config(clock)
1563 , m_cont(
1564 m_buck,
1565 std::cref(m_config.value_hash()),
1566 std::cref(m_config.key_value_equal()))
1567{
1568}
1569
1570template <
1571 bool IsMulti,
1572 bool IsMap,
1573 class Key,
1574 class T,
1575 class Clock,
1576 class Hash,
1577 class KeyEqual,
1578 class Allocator>
1580 IsMulti,
1581 IsMap,
1582 Key,
1583 T,
1584 Clock,
1585 Hash,
1586 KeyEqual,
1587 Allocator>::aged_unordered_container(clock_type& clock, Hash const& hash)
1588 : m_config(clock, hash)
1589 , m_cont(
1590 m_buck,
1591 std::cref(m_config.value_hash()),
1592 std::cref(m_config.key_value_equal()))
1593{
1594}
1595
1596template <
1597 bool IsMulti,
1598 bool IsMap,
1599 class Key,
1600 class T,
1601 class Clock,
1602 class Hash,
1603 class KeyEqual,
1604 class Allocator>
1606 IsMulti,
1607 IsMap,
1608 Key,
1609 T,
1610 Clock,
1611 Hash,
1612 KeyEqual,
1613 Allocator>::
1614 aged_unordered_container(clock_type& clock, KeyEqual const& key_eq)
1615 : m_config(clock, key_eq)
1616 , m_cont(
1617 m_buck,
1618 std::cref(m_config.value_hash()),
1619 std::cref(m_config.key_value_equal()))
1620{
1621}
1622
1623template <
1624 bool IsMulti,
1625 bool IsMap,
1626 class Key,
1627 class T,
1628 class Clock,
1629 class Hash,
1630 class KeyEqual,
1631 class Allocator>
1633 IsMulti,
1634 IsMap,
1635 Key,
1636 T,
1637 Clock,
1638 Hash,
1639 KeyEqual,
1640 Allocator>::
1641 aged_unordered_container(clock_type& clock, Allocator const& alloc)
1642 : m_config(clock, alloc)
1643 , m_buck(alloc)
1644 , m_cont(
1645 m_buck,
1646 std::cref(m_config.value_hash()),
1647 std::cref(m_config.key_value_equal()))
1648{
1649}
1650
1651template <
1652 bool IsMulti,
1653 bool IsMap,
1654 class Key,
1655 class T,
1656 class Clock,
1657 class Hash,
1658 class KeyEqual,
1659 class Allocator>
1661 IsMulti,
1662 IsMap,
1663 Key,
1664 T,
1665 Clock,
1666 Hash,
1667 KeyEqual,
1668 Allocator>::
1669 aged_unordered_container(
1670 clock_type& clock,
1671 Hash const& hash,
1672 KeyEqual const& key_eq)
1673 : m_config(clock, hash, key_eq)
1674 , m_cont(
1675 m_buck,
1676 std::cref(m_config.value_hash()),
1677 std::cref(m_config.key_value_equal()))
1678{
1679}
1680
1681template <
1682 bool IsMulti,
1683 bool IsMap,
1684 class Key,
1685 class T,
1686 class Clock,
1687 class Hash,
1688 class KeyEqual,
1689 class Allocator>
1691 IsMulti,
1692 IsMap,
1693 Key,
1694 T,
1695 Clock,
1696 Hash,
1697 KeyEqual,
1698 Allocator>::
1699 aged_unordered_container(
1700 clock_type& clock,
1701 Hash const& hash,
1702 Allocator const& alloc)
1703 : m_config(clock, hash, alloc)
1704 , m_buck(alloc)
1705 , m_cont(
1706 m_buck,
1707 std::cref(m_config.value_hash()),
1708 std::cref(m_config.key_value_equal()))
1709{
1710}
1711
1712template <
1713 bool IsMulti,
1714 bool IsMap,
1715 class Key,
1716 class T,
1717 class Clock,
1718 class Hash,
1719 class KeyEqual,
1720 class Allocator>
1722 IsMulti,
1723 IsMap,
1724 Key,
1725 T,
1726 Clock,
1727 Hash,
1728 KeyEqual,
1729 Allocator>::
1730 aged_unordered_container(
1731 clock_type& clock,
1732 KeyEqual const& key_eq,
1733 Allocator const& alloc)
1734 : m_config(clock, key_eq, alloc)
1735 , m_buck(alloc)
1736 , m_cont(
1737 m_buck,
1738 std::cref(m_config.value_hash()),
1739 std::cref(m_config.key_value_equal()))
1740{
1741}
1742
1743template <
1744 bool IsMulti,
1745 bool IsMap,
1746 class Key,
1747 class T,
1748 class Clock,
1749 class Hash,
1750 class KeyEqual,
1751 class Allocator>
1753 IsMulti,
1754 IsMap,
1755 Key,
1756 T,
1757 Clock,
1758 Hash,
1759 KeyEqual,
1760 Allocator>::
1761 aged_unordered_container(
1762 clock_type& clock,
1763 Hash const& hash,
1764 KeyEqual const& key_eq,
1765 Allocator const& alloc)
1766 : m_config(clock, hash, key_eq, alloc)
1767 , m_buck(alloc)
1768 , m_cont(
1769 m_buck,
1770 std::cref(m_config.value_hash()),
1771 std::cref(m_config.key_value_equal()))
1772{
1773}
1774
1775template <
1776 bool IsMulti,
1777 bool IsMap,
1778 class Key,
1779 class T,
1780 class Clock,
1781 class Hash,
1782 class KeyEqual,
1783 class Allocator>
1784template <class InputIt>
1786 IsMulti,
1787 IsMap,
1788 Key,
1789 T,
1790 Clock,
1791 Hash,
1792 KeyEqual,
1793 Allocator>::
1794 aged_unordered_container(InputIt first, InputIt last, clock_type& clock)
1795 : m_config(clock)
1796 , m_cont(
1797 m_buck,
1798 std::cref(m_config.value_hash()),
1799 std::cref(m_config.key_value_equal()))
1800{
1801 insert(first, last);
1802}
1803
1804template <
1805 bool IsMulti,
1806 bool IsMap,
1807 class Key,
1808 class T,
1809 class Clock,
1810 class Hash,
1811 class KeyEqual,
1812 class Allocator>
1813template <class InputIt>
1815 IsMulti,
1816 IsMap,
1817 Key,
1818 T,
1819 Clock,
1820 Hash,
1821 KeyEqual,
1822 Allocator>::
1823 aged_unordered_container(
1824 InputIt first,
1825 InputIt last,
1826 clock_type& clock,
1827 Hash const& hash)
1828 : m_config(clock, hash)
1829 , m_cont(
1830 m_buck,
1831 std::cref(m_config.value_hash()),
1832 std::cref(m_config.key_value_equal()))
1833{
1834 insert(first, last);
1835}
1836
1837template <
1838 bool IsMulti,
1839 bool IsMap,
1840 class Key,
1841 class T,
1842 class Clock,
1843 class Hash,
1844 class KeyEqual,
1845 class Allocator>
1846template <class InputIt>
1848 IsMulti,
1849 IsMap,
1850 Key,
1851 T,
1852 Clock,
1853 Hash,
1854 KeyEqual,
1855 Allocator>::
1856 aged_unordered_container(
1857 InputIt first,
1858 InputIt last,
1859 clock_type& clock,
1860 KeyEqual const& key_eq)
1861 : m_config(clock, key_eq)
1862 , m_cont(
1863 m_buck,
1864 std::cref(m_config.value_hash()),
1865 std::cref(m_config.key_value_equal()))
1866{
1867 insert(first, last);
1868}
1869
1870template <
1871 bool IsMulti,
1872 bool IsMap,
1873 class Key,
1874 class T,
1875 class Clock,
1876 class Hash,
1877 class KeyEqual,
1878 class Allocator>
1879template <class InputIt>
1881 IsMulti,
1882 IsMap,
1883 Key,
1884 T,
1885 Clock,
1886 Hash,
1887 KeyEqual,
1888 Allocator>::
1889 aged_unordered_container(
1890 InputIt first,
1891 InputIt last,
1892 clock_type& clock,
1893 Allocator const& alloc)
1894 : m_config(clock, alloc)
1895 , m_buck(alloc)
1896 , m_cont(
1897 m_buck,
1898 std::cref(m_config.value_hash()),
1899 std::cref(m_config.key_value_equal()))
1900{
1901 insert(first, last);
1902}
1903
1904template <
1905 bool IsMulti,
1906 bool IsMap,
1907 class Key,
1908 class T,
1909 class Clock,
1910 class Hash,
1911 class KeyEqual,
1912 class Allocator>
1913template <class InputIt>
1915 IsMulti,
1916 IsMap,
1917 Key,
1918 T,
1919 Clock,
1920 Hash,
1921 KeyEqual,
1922 Allocator>::
1923 aged_unordered_container(
1924 InputIt first,
1925 InputIt last,
1926 clock_type& clock,
1927 Hash const& hash,
1928 KeyEqual const& key_eq)
1929 : m_config(clock, hash, key_eq)
1930 , m_cont(
1931 m_buck,
1932 std::cref(m_config.value_hash()),
1933 std::cref(m_config.key_value_equal()))
1934{
1935 insert(first, last);
1936}
1937
1938template <
1939 bool IsMulti,
1940 bool IsMap,
1941 class Key,
1942 class T,
1943 class Clock,
1944 class Hash,
1945 class KeyEqual,
1946 class Allocator>
1947template <class InputIt>
1949 IsMulti,
1950 IsMap,
1951 Key,
1952 T,
1953 Clock,
1954 Hash,
1955 KeyEqual,
1956 Allocator>::
1957 aged_unordered_container(
1958 InputIt first,
1959 InputIt last,
1960 clock_type& clock,
1961 Hash const& hash,
1962 Allocator const& alloc)
1963 : m_config(clock, hash, alloc)
1964 , m_buck(alloc)
1965 , m_cont(
1966 m_buck,
1967 std::cref(m_config.value_hash()),
1968 std::cref(m_config.key_value_equal()))
1969{
1970 insert(first, last);
1971}
1972
1973template <
1974 bool IsMulti,
1975 bool IsMap,
1976 class Key,
1977 class T,
1978 class Clock,
1979 class Hash,
1980 class KeyEqual,
1981 class Allocator>
1982template <class InputIt>
1984 IsMulti,
1985 IsMap,
1986 Key,
1987 T,
1988 Clock,
1989 Hash,
1990 KeyEqual,
1991 Allocator>::
1992 aged_unordered_container(
1993 InputIt first,
1994 InputIt last,
1995 clock_type& clock,
1996 KeyEqual const& key_eq,
1997 Allocator const& alloc)
1998 : m_config(clock, key_eq, alloc)
1999 , m_buck(alloc)
2000 , m_cont(
2001 m_buck,
2002 std::cref(m_config.value_hash()),
2003 std::cref(m_config.key_value_equal()))
2004{
2005 insert(first, last);
2006}
2007
2008template <
2009 bool IsMulti,
2010 bool IsMap,
2011 class Key,
2012 class T,
2013 class Clock,
2014 class Hash,
2015 class KeyEqual,
2016 class Allocator>
2017template <class InputIt>
2019 IsMulti,
2020 IsMap,
2021 Key,
2022 T,
2023 Clock,
2024 Hash,
2025 KeyEqual,
2026 Allocator>::
2027 aged_unordered_container(
2028 InputIt first,
2029 InputIt last,
2030 clock_type& clock,
2031 Hash const& hash,
2032 KeyEqual const& key_eq,
2033 Allocator const& alloc)
2034 : m_config(clock, hash, key_eq, alloc)
2035 , m_buck(alloc)
2036 , m_cont(
2037 m_buck,
2038 std::cref(m_config.value_hash()),
2039 std::cref(m_config.key_value_equal()))
2040{
2041 insert(first, last);
2042}
2043
2044template <
2045 bool IsMulti,
2046 bool IsMap,
2047 class Key,
2048 class T,
2049 class Clock,
2050 class Hash,
2051 class KeyEqual,
2052 class Allocator>
2054 IsMulti,
2055 IsMap,
2056 Key,
2057 T,
2058 Clock,
2059 Hash,
2060 KeyEqual,
2061 Allocator>::aged_unordered_container(aged_unordered_container const& other)
2062 : m_config(other.m_config)
2063 , m_buck(m_config.alloc())
2064 , m_cont(
2065 m_buck,
2066 std::cref(m_config.value_hash()),
2067 std::cref(m_config.key_value_equal()))
2068{
2069 insert(other.cbegin(), other.cend());
2070}
2071
2072template <
2073 bool IsMulti,
2074 bool IsMap,
2075 class Key,
2076 class T,
2077 class Clock,
2078 class Hash,
2079 class KeyEqual,
2080 class Allocator>
2082 IsMulti,
2083 IsMap,
2084 Key,
2085 T,
2086 Clock,
2087 Hash,
2088 KeyEqual,
2089 Allocator>::
2090 aged_unordered_container(
2091 aged_unordered_container const& other,
2092 Allocator const& alloc)
2093 : m_config(other.m_config, alloc)
2094 , m_buck(alloc)
2095 , m_cont(
2096 m_buck,
2097 std::cref(m_config.value_hash()),
2098 std::cref(m_config.key_value_equal()))
2099{
2100 insert(other.cbegin(), other.cend());
2101}
2102
2103template <
2104 bool IsMulti,
2105 bool IsMap,
2106 class Key,
2107 class T,
2108 class Clock,
2109 class Hash,
2110 class KeyEqual,
2111 class Allocator>
2113 IsMulti,
2114 IsMap,
2115 Key,
2116 T,
2117 Clock,
2118 Hash,
2119 KeyEqual,
2120 Allocator>::aged_unordered_container(aged_unordered_container&& other)
2121 : m_config(std::move(other.m_config))
2122 , m_buck(std::move(other.m_buck))
2123 , m_cont(std::move(other.m_cont))
2124{
2125 chronological.list = std::move(other.chronological.list);
2126}
2127
2128template <
2129 bool IsMulti,
2130 bool IsMap,
2131 class Key,
2132 class T,
2133 class Clock,
2134 class Hash,
2135 class KeyEqual,
2136 class Allocator>
2138 IsMulti,
2139 IsMap,
2140 Key,
2141 T,
2142 Clock,
2143 Hash,
2144 KeyEqual,
2145 Allocator>::
2146 aged_unordered_container(
2148 Allocator const& alloc)
2149 : m_config(std::move(other.m_config), alloc)
2150 , m_buck(alloc)
2151 , m_cont(
2152 m_buck,
2153 std::cref(m_config.value_hash()),
2154 std::cref(m_config.key_value_equal()))
2155{
2156 insert(other.cbegin(), other.cend());
2157 other.clear();
2158}
2159
2160template <
2161 bool IsMulti,
2162 bool IsMap,
2163 class Key,
2164 class T,
2165 class Clock,
2166 class Hash,
2167 class KeyEqual,
2168 class Allocator>
2170 IsMulti,
2171 IsMap,
2172 Key,
2173 T,
2174 Clock,
2175 Hash,
2176 KeyEqual,
2177 Allocator>::
2178 aged_unordered_container(
2180 clock_type& clock)
2181 : m_config(clock)
2182 , m_cont(
2183 m_buck,
2184 std::cref(m_config.value_hash()),
2185 std::cref(m_config.key_value_equal()))
2186{
2187 insert(init.begin(), init.end());
2188}
2189
2190template <
2191 bool IsMulti,
2192 bool IsMap,
2193 class Key,
2194 class T,
2195 class Clock,
2196 class Hash,
2197 class KeyEqual,
2198 class Allocator>
2200 IsMulti,
2201 IsMap,
2202 Key,
2203 T,
2204 Clock,
2205 Hash,
2206 KeyEqual,
2207 Allocator>::
2208 aged_unordered_container(
2210 clock_type& clock,
2211 Hash const& hash)
2212 : m_config(clock, hash)
2213 , m_cont(
2214 m_buck,
2215 std::cref(m_config.value_hash()),
2216 std::cref(m_config.key_value_equal()))
2217{
2218 insert(init.begin(), init.end());
2219}
2220
2221template <
2222 bool IsMulti,
2223 bool IsMap,
2224 class Key,
2225 class T,
2226 class Clock,
2227 class Hash,
2228 class KeyEqual,
2229 class Allocator>
2231 IsMulti,
2232 IsMap,
2233 Key,
2234 T,
2235 Clock,
2236 Hash,
2237 KeyEqual,
2238 Allocator>::
2239 aged_unordered_container(
2241 clock_type& clock,
2242 KeyEqual const& key_eq)
2243 : m_config(clock, key_eq)
2244 , m_cont(
2245 m_buck,
2246 std::cref(m_config.value_hash()),
2247 std::cref(m_config.key_value_equal()))
2248{
2249 insert(init.begin(), init.end());
2250}
2251
2252template <
2253 bool IsMulti,
2254 bool IsMap,
2255 class Key,
2256 class T,
2257 class Clock,
2258 class Hash,
2259 class KeyEqual,
2260 class Allocator>
2262 IsMulti,
2263 IsMap,
2264 Key,
2265 T,
2266 Clock,
2267 Hash,
2268 KeyEqual,
2269 Allocator>::
2270 aged_unordered_container(
2272 clock_type& clock,
2273 Allocator const& alloc)
2274 : m_config(clock, alloc)
2275 , m_buck(alloc)
2276 , m_cont(
2277 m_buck,
2278 std::cref(m_config.value_hash()),
2279 std::cref(m_config.key_value_equal()))
2280{
2281 insert(init.begin(), init.end());
2282}
2283
2284template <
2285 bool IsMulti,
2286 bool IsMap,
2287 class Key,
2288 class T,
2289 class Clock,
2290 class Hash,
2291 class KeyEqual,
2292 class Allocator>
2294 IsMulti,
2295 IsMap,
2296 Key,
2297 T,
2298 Clock,
2299 Hash,
2300 KeyEqual,
2301 Allocator>::
2302 aged_unordered_container(
2304 clock_type& clock,
2305 Hash const& hash,
2306 KeyEqual const& key_eq)
2307 : m_config(clock, hash, key_eq)
2308 , m_cont(
2309 m_buck,
2310 std::cref(m_config.value_hash()),
2311 std::cref(m_config.key_value_equal()))
2312{
2313 insert(init.begin(), init.end());
2314}
2315
2316template <
2317 bool IsMulti,
2318 bool IsMap,
2319 class Key,
2320 class T,
2321 class Clock,
2322 class Hash,
2323 class KeyEqual,
2324 class Allocator>
2326 IsMulti,
2327 IsMap,
2328 Key,
2329 T,
2330 Clock,
2331 Hash,
2332 KeyEqual,
2333 Allocator>::
2334 aged_unordered_container(
2336 clock_type& clock,
2337 Hash const& hash,
2338 Allocator const& alloc)
2339 : m_config(clock, hash, alloc)
2340 , m_buck(alloc)
2341 , m_cont(
2342 m_buck,
2343 std::cref(m_config.value_hash()),
2344 std::cref(m_config.key_value_equal()))
2345{
2346 insert(init.begin(), init.end());
2347}
2348
2349template <
2350 bool IsMulti,
2351 bool IsMap,
2352 class Key,
2353 class T,
2354 class Clock,
2355 class Hash,
2356 class KeyEqual,
2357 class Allocator>
2359 IsMulti,
2360 IsMap,
2361 Key,
2362 T,
2363 Clock,
2364 Hash,
2365 KeyEqual,
2366 Allocator>::
2367 aged_unordered_container(
2369 clock_type& clock,
2370 KeyEqual const& key_eq,
2371 Allocator const& alloc)
2372 : m_config(clock, key_eq, alloc)
2373 , m_buck(alloc)
2374 , m_cont(
2375 m_buck,
2376 std::cref(m_config.value_hash()),
2377 std::cref(m_config.key_value_equal()))
2378{
2379 insert(init.begin(), init.end());
2380}
2381
2382template <
2383 bool IsMulti,
2384 bool IsMap,
2385 class Key,
2386 class T,
2387 class Clock,
2388 class Hash,
2389 class KeyEqual,
2390 class Allocator>
2392 IsMulti,
2393 IsMap,
2394 Key,
2395 T,
2396 Clock,
2397 Hash,
2398 KeyEqual,
2399 Allocator>::
2400 aged_unordered_container(
2402 clock_type& clock,
2403 Hash const& hash,
2404 KeyEqual const& key_eq,
2405 Allocator const& alloc)
2406 : m_config(clock, hash, key_eq, alloc)
2407 , m_buck(alloc)
2408 , m_cont(
2409 m_buck,
2410 std::cref(m_config.value_hash()),
2411 std::cref(m_config.key_value_equal()))
2412{
2413 insert(init.begin(), init.end());
2414}
2415
2416template <
2417 bool IsMulti,
2418 bool IsMap,
2419 class Key,
2420 class T,
2421 class Clock,
2422 class Hash,
2423 class KeyEqual,
2424 class Allocator>
2426 IsMulti,
2427 IsMap,
2428 Key,
2429 T,
2430 Clock,
2431 Hash,
2432 KeyEqual,
2433 Allocator>::~aged_unordered_container()
2434{
2435 clear();
2436}
2437
2438template <
2439 bool IsMulti,
2440 bool IsMap,
2441 class Key,
2442 class T,
2443 class Clock,
2444 class Hash,
2445 class KeyEqual,
2446 class Allocator>
2447auto
2449 IsMulti,
2450 IsMap,
2451 Key,
2452 T,
2453 Clock,
2454 Hash,
2455 KeyEqual,
2456 Allocator>::operator=(aged_unordered_container const& other)
2458{
2459 if (this != &other)
2460 {
2461 size_type const n(other.size());
2462 clear();
2463 m_config = other.m_config;
2464 m_buck = Buckets(m_config.alloc());
2465 maybe_rehash(n);
2466 insert_unchecked(other.begin(), other.end());
2467 }
2468 return *this;
2469}
2470
2471template <
2472 bool IsMulti,
2473 bool IsMap,
2474 class Key,
2475 class T,
2476 class Clock,
2477 class Hash,
2478 class KeyEqual,
2479 class Allocator>
2480auto
2482 IsMulti,
2483 IsMap,
2484 Key,
2485 T,
2486 Clock,
2487 Hash,
2488 KeyEqual,
2489 Allocator>::operator=(aged_unordered_container&& other)
2491{
2492 size_type const n(other.size());
2493 clear();
2494 m_config = std::move(other.m_config);
2495 m_buck = Buckets(m_config.alloc());
2496 maybe_rehash(n);
2497 insert_unchecked(other.begin(), other.end());
2498 other.clear();
2499 return *this;
2500}
2501
2502template <
2503 bool IsMulti,
2504 bool IsMap,
2505 class Key,
2506 class T,
2507 class Clock,
2508 class Hash,
2509 class KeyEqual,
2510 class Allocator>
2511auto
2513 IsMulti,
2514 IsMap,
2515 Key,
2516 T,
2517 Clock,
2518 Hash,
2519 KeyEqual,
2520 Allocator>::operator=(std::initializer_list<value_type> init)
2522{
2523 clear();
2524 insert(init);
2525 return *this;
2526}
2527
2528//------------------------------------------------------------------------------
2529
2530template <
2531 bool IsMulti,
2532 bool IsMap,
2533 class Key,
2534 class T,
2535 class Clock,
2536 class Hash,
2537 class KeyEqual,
2538 class Allocator>
2539template <class K, bool maybe_multi, bool maybe_map, class>
2542 IsMulti,
2543 IsMap,
2544 Key,
2545 T,
2546 Clock,
2547 Hash,
2548 KeyEqual,
2549 Allocator>::at(K const& k)
2550{
2551 auto const iter(m_cont.find(
2552 k,
2553 std::cref(m_config.hash_function()),
2554 std::cref(m_config.key_value_equal())));
2555 if (iter == m_cont.end())
2556 throw std::out_of_range("key not found");
2557 return iter->value.second;
2558}
2559
2560template <
2561 bool IsMulti,
2562 bool IsMap,
2563 class Key,
2564 class T,
2565 class Clock,
2566 class Hash,
2567 class KeyEqual,
2568 class Allocator>
2569template <class K, bool maybe_multi, bool maybe_map, class>
2572 IsMulti,
2573 IsMap,
2574 Key,
2575 T,
2576 Clock,
2577 Hash,
2578 KeyEqual,
2579 Allocator>::at(K const& k) const
2580{
2581 auto const iter(m_cont.find(
2582 k,
2583 std::cref(m_config.hash_function()),
2584 std::cref(m_config.key_value_equal())));
2585 if (iter == m_cont.end())
2586 throw std::out_of_range("key not found");
2587 return iter->value.second;
2588}
2589
2590template <
2591 bool IsMulti,
2592 bool IsMap,
2593 class Key,
2594 class T,
2595 class Clock,
2596 class Hash,
2597 class KeyEqual,
2598 class Allocator>
2599template <bool maybe_multi, bool maybe_map, class>
2602 IsMulti,
2603 IsMap,
2604 Key,
2605 T,
2606 Clock,
2607 Hash,
2608 KeyEqual,
2609 Allocator>::operator[](Key const& key)
2610{
2611 maybe_rehash(1);
2612 typename cont_type::insert_commit_data d;
2613 auto const result(m_cont.insert_check(
2614 key,
2615 std::cref(m_config.hash_function()),
2616 std::cref(m_config.key_value_equal()),
2617 d));
2618 if (result.second)
2619 {
2620 element* const p(new_element(
2624 m_cont.insert_commit(*p, d);
2625 chronological.list.push_back(*p);
2626 return p->value.second;
2627 }
2628 return result.first->value.second;
2629}
2630
2631template <
2632 bool IsMulti,
2633 bool IsMap,
2634 class Key,
2635 class T,
2636 class Clock,
2637 class Hash,
2638 class KeyEqual,
2639 class Allocator>
2640template <bool maybe_multi, bool maybe_map, class>
2643 IsMulti,
2644 IsMap,
2645 Key,
2646 T,
2647 Clock,
2648 Hash,
2649 KeyEqual,
2650 Allocator>::operator[](Key&& key)
2651{
2652 maybe_rehash(1);
2653 typename cont_type::insert_commit_data d;
2654 auto const result(m_cont.insert_check(
2655 key,
2656 std::cref(m_config.hash_function()),
2657 std::cref(m_config.key_value_equal()),
2658 d));
2659 if (result.second)
2660 {
2661 element* const p(new_element(
2663 std::forward_as_tuple(std::move(key)),
2665 m_cont.insert_commit(*p, d);
2666 chronological.list.push_back(*p);
2667 return p->value.second;
2668 }
2669 return result.first->value.second;
2670}
2671
2672//------------------------------------------------------------------------------
2673
2674template <
2675 bool IsMulti,
2676 bool IsMap,
2677 class Key,
2678 class T,
2679 class Clock,
2680 class Hash,
2681 class KeyEqual,
2682 class Allocator>
2683void
2685 IsMulti,
2686 IsMap,
2687 Key,
2688 T,
2689 Clock,
2690 Hash,
2691 KeyEqual,
2692 Allocator>::clear()
2693{
2694 for (auto iter(chronological.list.begin());
2695 iter != chronological.list.end();)
2696 unlink_and_delete_element(&*iter++);
2697 chronological.list.clear();
2698 m_cont.clear();
2699 m_buck.clear();
2700}
2701
2702// map, set
2703template <
2704 bool IsMulti,
2705 bool IsMap,
2706 class Key,
2707 class T,
2708 class Clock,
2709 class Hash,
2710 class KeyEqual,
2711 class Allocator>
2712template <bool maybe_multi>
2713auto
2715 IsMulti,
2716 IsMap,
2717 Key,
2718 T,
2719 Clock,
2720 Hash,
2721 KeyEqual,
2722 Allocator>::insert(value_type const& value) ->
2724{
2725 maybe_rehash(1);
2726 typename cont_type::insert_commit_data d;
2727 auto const result(m_cont.insert_check(
2728 extract(value),
2729 std::cref(m_config.hash_function()),
2730 std::cref(m_config.key_value_equal()),
2731 d));
2732 if (result.second)
2733 {
2734 element* const p(new_element(value));
2735 auto const iter(m_cont.insert_commit(*p, d));
2736 chronological.list.push_back(*p);
2737 return std::make_pair(iterator(iter), true);
2738 }
2739 return std::make_pair(iterator(result.first), false);
2740}
2741
2742// multimap, multiset
2743template <
2744 bool IsMulti,
2745 bool IsMap,
2746 class Key,
2747 class T,
2748 class Clock,
2749 class Hash,
2750 class KeyEqual,
2751 class Allocator>
2752template <bool maybe_multi>
2753auto
2755 IsMulti,
2756 IsMap,
2757 Key,
2758 T,
2759 Clock,
2760 Hash,
2761 KeyEqual,
2762 Allocator>::insert(value_type const& value) ->
2764{
2765 maybe_rehash(1);
2766 element* const p(new_element(value));
2767 chronological.list.push_back(*p);
2768 auto const iter(m_cont.insert(*p));
2769 return iterator(iter);
2770}
2771
2772// map, set
2773template <
2774 bool IsMulti,
2775 bool IsMap,
2776 class Key,
2777 class T,
2778 class Clock,
2779 class Hash,
2780 class KeyEqual,
2781 class Allocator>
2782template <bool maybe_multi, bool maybe_map>
2783auto
2784aged_unordered_container<
2785 IsMulti,
2786 IsMap,
2787 Key,
2788 T,
2789 Clock,
2790 Hash,
2791 KeyEqual,
2792 Allocator>::insert(value_type&& value) ->
2793 typename std::
2795{
2796 maybe_rehash(1);
2797 typename cont_type::insert_commit_data d;
2798 auto const result(m_cont.insert_check(
2799 extract(value),
2800 std::cref(m_config.hash_function()),
2801 std::cref(m_config.key_value_equal()),
2802 d));
2803 if (result.second)
2804 {
2805 element* const p(new_element(std::move(value)));
2806 auto const iter(m_cont.insert_commit(*p, d));
2807 chronological.list.push_back(*p);
2808 return std::make_pair(iterator(iter), true);
2809 }
2810 return std::make_pair(iterator(result.first), false);
2811}
2812
2813// multimap, multiset
2814template <
2815 bool IsMulti,
2816 bool IsMap,
2817 class Key,
2818 class T,
2819 class Clock,
2820 class Hash,
2821 class KeyEqual,
2822 class Allocator>
2823template <bool maybe_multi, bool maybe_map>
2824auto
2826 IsMulti,
2827 IsMap,
2828 Key,
2829 T,
2830 Clock,
2831 Hash,
2832 KeyEqual,
2833 Allocator>::insert(value_type&& value) ->
2835{
2836 maybe_rehash(1);
2837 element* const p(new_element(std::move(value)));
2838 chronological.list.push_back(*p);
2839 auto const iter(m_cont.insert(*p));
2840 return iterator(iter);
2841}
2842
2843#if 1 // Use insert() instead of insert_check() insert_commit()
2844// set, map
2845template <
2846 bool IsMulti,
2847 bool IsMap,
2848 class Key,
2849 class T,
2850 class Clock,
2851 class Hash,
2852 class KeyEqual,
2853 class Allocator>
2854template <bool maybe_multi, class... Args>
2855auto
2856aged_unordered_container<
2857 IsMulti,
2858 IsMap,
2859 Key,
2860 T,
2861 Clock,
2862 Hash,
2863 KeyEqual,
2864 Allocator>::emplace(Args&&... args) ->
2866{
2867 maybe_rehash(1);
2868 // VFALCO NOTE Its unfortunate that we need to
2869 // construct element here
2870 element* const p(new_element(std::forward<Args>(args)...));
2871 auto const result(m_cont.insert(*p));
2872 if (result.second)
2873 {
2874 chronological.list.push_back(*p);
2875 return std::make_pair(iterator(result.first), true);
2876 }
2877 delete_element(p);
2878 return std::make_pair(iterator(result.first), false);
2879}
2880#else // As original, use insert_check() / insert_commit () pair.
2881// set, map
2882template <
2883 bool IsMulti,
2884 bool IsMap,
2885 class Key,
2886 class T,
2887 class Clock,
2888 class Hash,
2889 class KeyEqual,
2890 class Allocator>
2891template <bool maybe_multi, class... Args>
2892auto
2894 IsMulti,
2895 IsMap,
2896 Key,
2897 T,
2898 Clock,
2899 Hash,
2900 KeyEqual,
2901 Allocator>::emplace(Args&&... args) ->
2903{
2904 maybe_rehash(1);
2905 // VFALCO NOTE Its unfortunate that we need to
2906 // construct element here
2907 element* const p(new_element(std::forward<Args>(args)...));
2908 typename cont_type::insert_commit_data d;
2909 auto const result(m_cont.insert_check(
2910 extract(p->value),
2911 std::cref(m_config.hash_function()),
2912 std::cref(m_config.key_value_equal()),
2913 d));
2914 if (result.second)
2915 {
2916 auto const iter(m_cont.insert_commit(*p, d));
2917 chronological.list.push_back(*p);
2918 return std::make_pair(iterator(iter), true);
2919 }
2920 delete_element(p);
2921 return std::make_pair(iterator(result.first), false);
2922}
2923#endif // 0
2924
2925// multiset, multimap
2926template <
2927 bool IsMulti,
2928 bool IsMap,
2929 class Key,
2930 class T,
2931 class Clock,
2932 class Hash,
2933 class KeyEqual,
2934 class Allocator>
2935template <bool maybe_multi, class... Args>
2936auto
2937aged_unordered_container<
2938 IsMulti,
2939 IsMap,
2940 Key,
2941 T,
2942 Clock,
2943 Hash,
2944 KeyEqual,
2945 Allocator>::emplace(Args&&... args) ->
2947{
2948 maybe_rehash(1);
2949 element* const p(new_element(std::forward<Args>(args)...));
2950 chronological.list.push_back(*p);
2951 auto const iter(m_cont.insert(*p));
2952 return iterator(iter);
2953}
2954
2955// set, map
2956template <
2957 bool IsMulti,
2958 bool IsMap,
2959 class Key,
2960 class T,
2961 class Clock,
2962 class Hash,
2963 class KeyEqual,
2964 class Allocator>
2965template <bool maybe_multi, class... Args>
2966auto
2967aged_unordered_container<
2968 IsMulti,
2969 IsMap,
2970 Key,
2971 T,
2972 Clock,
2973 Hash,
2974 KeyEqual,
2975 Allocator>::emplace_hint(const_iterator /*hint*/, Args&&... args) ->
2977{
2978 maybe_rehash(1);
2979 // VFALCO NOTE Its unfortunate that we need to
2980 // construct element here
2981 element* const p(new_element(std::forward<Args>(args)...));
2982 typename cont_type::insert_commit_data d;
2983 auto const result(m_cont.insert_check(
2984 extract(p->value),
2985 std::cref(m_config.hash_function()),
2986 std::cref(m_config.key_value_equal()),
2987 d));
2988 if (result.second)
2989 {
2990 auto const iter(m_cont.insert_commit(*p, d));
2991 chronological.list.push_back(*p);
2992 return std::make_pair(iterator(iter), true);
2993 }
2994 delete_element(p);
2995 return std::make_pair(iterator(result.first), false);
2996}
2997
2998template <
2999 bool IsMulti,
3000 bool IsMap,
3001 class Key,
3002 class T,
3003 class Clock,
3004 class Hash,
3005 class KeyEqual,
3006 class Allocator>
3007template <bool is_const, class Iterator>
3010 IsMulti,
3011 IsMap,
3012 Key,
3013 T,
3014 Clock,
3015 Hash,
3016 KeyEqual,
3018 pos)
3019{
3020 unlink_and_delete_element(&*((pos++).iterator()));
3022 pos.iterator());
3023}
3024
3025template <
3026 bool IsMulti,
3027 bool IsMap,
3028 class Key,
3029 class T,
3030 class Clock,
3031 class Hash,
3032 class KeyEqual,
3033 class Allocator>
3034template <bool is_const, class Iterator>
3037 IsMulti,
3038 IsMap,
3039 Key,
3040 T,
3041 Clock,
3042 Hash,
3043 KeyEqual,
3044 Allocator>::
3045 erase(
3048{
3049 for (; first != last;)
3050 unlink_and_delete_element(&*((first++).iterator()));
3051
3053 first.iterator());
3054}
3055
3056template <
3057 bool IsMulti,
3058 bool IsMap,
3059 class Key,
3060 class T,
3061 class Clock,
3062 class Hash,
3063 class KeyEqual,
3064 class Allocator>
3065template <class K>
3066auto
3068 IsMulti,
3069 IsMap,
3070 Key,
3071 T,
3072 Clock,
3073 Hash,
3074 KeyEqual,
3075 Allocator>::erase(K const& k) -> size_type
3076{
3077 auto iter(m_cont.find(
3078 k,
3079 std::cref(m_config.hash_function()),
3080 std::cref(m_config.key_value_equal())));
3081 if (iter == m_cont.end())
3082 return 0;
3083 size_type n(0);
3084 for (;;)
3085 {
3086 auto p(&*iter++);
3087 bool const done(m_config(*p, extract(iter->value)));
3088 unlink_and_delete_element(p);
3089 ++n;
3090 if (done)
3091 break;
3092 }
3093 return n;
3094}
3095
3096template <
3097 bool IsMulti,
3098 bool IsMap,
3099 class Key,
3100 class T,
3101 class Clock,
3102 class Hash,
3103 class KeyEqual,
3104 class Allocator>
3105void
3107 IsMulti,
3108 IsMap,
3109 Key,
3110 T,
3111 Clock,
3112 Hash,
3113 KeyEqual,
3114 Allocator>::swap(aged_unordered_container& other) noexcept
3115{
3116 swap_data(other);
3117 std::swap(chronological, other.chronological);
3118 std::swap(m_cont, other.m_cont);
3119}
3120
3121template <
3122 bool IsMulti,
3123 bool IsMap,
3124 class Key,
3125 class T,
3126 class Clock,
3127 class Hash,
3128 class KeyEqual,
3129 class Allocator>
3130template <class K>
3131auto
3133 IsMulti,
3134 IsMap,
3135 Key,
3136 T,
3137 Clock,
3138 Hash,
3139 KeyEqual,
3140 Allocator>::touch(K const& k) -> size_type
3141{
3142 auto const now(clock().now());
3143 size_type n(0);
3144 auto const range(equal_range(k));
3145 for (auto iter : range)
3146 {
3147 touch(iter, now);
3148 ++n;
3149 }
3150 return n;
3151}
3152
3153template <
3154 bool IsMulti,
3155 bool IsMap,
3156 class Key,
3157 class T,
3158 class Clock,
3159 class Hash,
3160 class KeyEqual,
3161 class Allocator>
3162template <
3163 bool OtherIsMap,
3164 class OtherKey,
3165 class OtherT,
3166 class OtherDuration,
3167 class OtherHash,
3168 class OtherAllocator,
3169 bool maybe_multi>
3172 IsMulti,
3173 IsMap,
3174 Key,
3175 T,
3176 Clock,
3177 Hash,
3178 KeyEqual,
3179 Allocator>::
3180operator==(aged_unordered_container<
3181 false,
3182 OtherIsMap,
3183 OtherKey,
3184 OtherT,
3185 OtherDuration,
3186 OtherHash,
3187 KeyEqual,
3188 OtherAllocator> const& other) const
3189{
3190 if (size() != other.size())
3191 return false;
3192 for (auto iter(cbegin()), last(cend()), olast(other.cend()); iter != last;
3193 ++iter)
3194 {
3195 auto oiter(other.find(extract(*iter)));
3196 if (oiter == olast)
3197 return false;
3198 }
3199 return true;
3200}
3201
3202template <
3203 bool IsMulti,
3204 bool IsMap,
3205 class Key,
3206 class T,
3207 class Clock,
3208 class Hash,
3209 class KeyEqual,
3210 class Allocator>
3211template <
3212 bool OtherIsMap,
3213 class OtherKey,
3214 class OtherT,
3215 class OtherDuration,
3216 class OtherHash,
3217 class OtherAllocator,
3218 bool maybe_multi>
3221 IsMulti,
3222 IsMap,
3223 Key,
3224 T,
3225 Clock,
3226 Hash,
3227 KeyEqual,
3228 Allocator>::
3229operator==(aged_unordered_container<
3230 true,
3231 OtherIsMap,
3232 OtherKey,
3233 OtherT,
3234 OtherDuration,
3235 OtherHash,
3236 KeyEqual,
3237 OtherAllocator> const& other) const
3238{
3239 if (size() != other.size())
3240 return false;
3241 for (auto iter(cbegin()), last(cend()); iter != last;)
3242 {
3243 auto const& k(extract(*iter));
3244 auto const eq(equal_range(k));
3245 auto const oeq(other.equal_range(k));
3246#if BEAST_NO_CXX14_IS_PERMUTATION
3247 if (std::distance(eq.first, eq.second) !=
3248 std::distance(oeq.first, oeq.second) ||
3249 !std::is_permutation(eq.first, eq.second, oeq.first))
3250 return false;
3251#else
3252 if (!std::is_permutation(eq.first, eq.second, oeq.first, oeq.second))
3253 return false;
3254#endif
3255 iter = eq.second;
3256 }
3257 return true;
3258}
3259
3260//------------------------------------------------------------------------------
3261
3262// map, set
3263template <
3264 bool IsMulti,
3265 bool IsMap,
3266 class Key,
3267 class T,
3268 class Clock,
3269 class Hash,
3270 class KeyEqual,
3271 class Allocator>
3272template <bool maybe_multi>
3273auto
3275 IsMulti,
3276 IsMap,
3277 Key,
3278 T,
3279 Clock,
3280 Hash,
3281 KeyEqual,
3282 Allocator>::insert_unchecked(value_type const& value) ->
3284{
3285 typename cont_type::insert_commit_data d;
3286 auto const result(m_cont.insert_check(
3287 extract(value),
3288 std::cref(m_config.hash_function()),
3289 std::cref(m_config.key_value_equal()),
3290 d));
3291 if (result.second)
3292 {
3293 element* const p(new_element(value));
3294 auto const iter(m_cont.insert_commit(*p, d));
3295 chronological.list.push_back(*p);
3296 return std::make_pair(iterator(iter), true);
3297 }
3298 return std::make_pair(iterator(result.first), false);
3299}
3300
3301// multimap, multiset
3302template <
3303 bool IsMulti,
3304 bool IsMap,
3305 class Key,
3306 class T,
3307 class Clock,
3308 class Hash,
3309 class KeyEqual,
3310 class Allocator>
3311template <bool maybe_multi>
3312auto
3314 IsMulti,
3315 IsMap,
3316 Key,
3317 T,
3318 Clock,
3319 Hash,
3320 KeyEqual,
3321 Allocator>::insert_unchecked(value_type const& value) ->
3323{
3324 element* const p(new_element(value));
3325 chronological.list.push_back(*p);
3326 auto const iter(m_cont.insert(*p));
3327 return iterator(iter);
3328}
3329
3330//------------------------------------------------------------------------------
3331
3332} // namespace detail
3333
3334//------------------------------------------------------------------------------
3335
3336template <
3337 bool IsMulti,
3338 bool IsMap,
3339 class Key,
3340 class T,
3341 class Clock,
3342 class Hash,
3343 class KeyEqual,
3344 class Allocator>
3346 IsMulti,
3347 IsMap,
3348 Key,
3349 T,
3350 Clock,
3351 Hash,
3352 KeyEqual,
3353 Allocator>> : std::true_type
3354{
3355 explicit is_aged_container() = default;
3356};
3357
3358// Free functions
3359
3360template <
3361 bool IsMulti,
3362 bool IsMap,
3363 class Key,
3364 class T,
3365 class Clock,
3366 class Hash,
3367 class KeyEqual,
3368 class Allocator>
3369void
3372 IsMulti,
3373 IsMap,
3374 Key,
3375 T,
3376 Clock,
3377 Hash,
3378 KeyEqual,
3379 Allocator>& lhs,
3381 IsMulti,
3382 IsMap,
3383 Key,
3384 T,
3385 Clock,
3386 Hash,
3387 KeyEqual,
3388 Allocator>& rhs) noexcept
3389{
3390 lhs.swap(rhs);
3391}
3392
3394template <
3395 bool IsMulti,
3396 bool IsMap,
3397 class Key,
3398 class T,
3399 class Clock,
3400 class Hash,
3401 class KeyEqual,
3402 class Allocator,
3403 class Rep,
3404 class Period>
3408 IsMulti,
3409 IsMap,
3410 Key,
3411 T,
3412 Clock,
3413 Hash,
3414 KeyEqual,
3415 Allocator>& c,
3416 std::chrono::duration<Rep, Period> const& age) noexcept
3417{
3418 std::size_t n(0);
3419 auto const expired(c.clock().now() - age);
3420 for (auto iter(c.chronological.cbegin());
3421 iter != c.chronological.cend() && iter.when() <= expired;)
3422 {
3423 iter = c.erase(iter);
3424 ++n;
3425 }
3426 return n;
3427}
3428
3429} // namespace beast
3430
3431#endif
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<!IsMap, typename list_type::iterator > iterator
beast::detail::aged_container_iterator< true, typename list_type::iterator > const_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.
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
typename boost::intrusive::make_list< element, boost::intrusive::constant_time_size< false > >::type list_type
aged_unordered_container(std::initializer_list< value_type > init, clock_type &clock, KeyEqual const &key_eq, Allocator const &alloc)
typename std::allocator_traits< Allocator >::template rebind_alloc< element > ElementAllocator
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::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
beast::detail::aged_container_iterator<!IsMap, typename cont_type::local_iterator > local_iterator
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
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
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
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< true, typename cont_type::local_iterator > const_local_iterator
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)
beast::detail::aged_container_iterator<!IsMap, typename cont_type::iterator > iterator
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
void swap(aged_unordered_container &other) noexcept
aged_unordered_container(InputIt first, InputIt last, clock_type &clock)
aged_unordered_container(aged_unordered_container &&other)
beast::detail::aged_container_iterator< true, typename cont_type::iterator > const_iterator
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
auto insert(value_type &&value) -> typename std::enable_if< !maybe_multi &&!maybe_map, std::pair< iterator, bool > >::type
typename std::allocator_traits< Allocator >::template rebind_alloc< element > BucketAllocator
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)