rippled
Loading...
Searching...
No Matches
aged_unordered_container.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of Beast: https://github.com/vinniefalco/Beast
4 Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef BEAST_CONTAINER_DETAIL_AGED_UNORDERED_CONTAINER_H_INCLUDED
21#define BEAST_CONTAINER_DETAIL_AGED_UNORDERED_CONTAINER_H_INCLUDED
22
23#include <xrpl/beast/clock/abstract_clock.h>
24#include <xrpl/beast/container/aged_container.h>
25#include <xrpl/beast/container/detail/aged_associative_container.h>
26#include <xrpl/beast/container/detail/aged_container_iterator.h>
27#include <xrpl/beast/container/detail/empty_base_optimization.h>
28
29#include <boost/intrusive/list.hpp>
30#include <boost/intrusive/unordered_set.hpp>
31
32#include <algorithm>
33#include <cmath>
34#include <functional>
35#include <initializer_list>
36#include <iterator>
37#include <memory>
38#include <type_traits>
39#include <utility>
40
41/*
42
43TODO
44
45- Add constructor variations that take a bucket count
46
47- Review for noexcept and exception guarantees
48
49- Call the safe version of is_permutation that takes 4 iterators
50
51*/
52
53#ifndef BEAST_NO_CXX14_IS_PERMUTATION
54#define BEAST_NO_CXX14_IS_PERMUTATION 1
55#endif
56
57namespace beast {
58namespace detail {
59
77template <
78 bool IsMulti,
79 bool IsMap,
80 class Key,
81 class T,
82 class Clock = std::chrono::steady_clock,
83 class Hash = std::hash<Key>,
84 class KeyEqual = std::equal_to<Key>,
85 class Allocator = std::allocator<
88{
89public:
93 using key_type = Key;
94 using mapped_type = T;
95 using value_type =
99
100 // Introspection (for unit tests)
104
105private:
106 static Key const&
107 extract(value_type const& value)
108 {
110 }
111
112 // VFALCO TODO hoist to remove template argument dependencies
113 struct element
114 : boost::intrusive::unordered_set_base_hook<
115 boost::intrusive::link_mode<boost::intrusive::normal_link>>,
116 boost::intrusive::list_base_hook<
117 boost::intrusive::link_mode<boost::intrusive::normal_link>>
118 {
119 // Stash types here so the iterator doesn't
120 // need to see the container declaration.
121 struct stashed
122 {
123 explicit stashed() = default;
124
127 };
128
129 element(time_point const& when_, value_type const& value_)
130 : value(value_), when(when_)
131 {
132 }
133
134 element(time_point const& when_, value_type&& value_)
135 : value(std::move(value_)), when(when_)
136 {
137 }
138
139 template <
140 class... Args,
141 class = typename std::enable_if<
143 element(time_point const& when_, Args&&... args)
144 : value(std::forward<Args>(args)...), when(when_)
145 {
146 }
147
150 };
151
152 // VFALCO TODO hoist to remove template argument dependencies
153 class ValueHash : public Hash
154 {
155 public:
157 using result_type = size_t;
158
160 {
161 }
162
163 ValueHash(Hash const& h) : Hash(h)
164 {
165 }
166
168 operator()(element const& e) const
169 {
170 return Hash::operator()(extract(e.value));
171 }
172
173 Hash&
175 {
176 return *this;
177 }
178
179 Hash const&
181 {
182 return *this;
183 }
184 };
185
186 // Compares value_type against element, used in find/insert_check
187 // VFALCO TODO hoist to remove template argument dependencies
188 class KeyValueEqual : public KeyEqual
189 {
190 public:
193 using result_type = bool;
194
196 {
197 }
198
199 KeyValueEqual(KeyEqual const& keyEqual) : KeyEqual(keyEqual)
200 {
201 }
202
203 bool
204 operator()(Key const& k, element const& e) const
205 {
206 return KeyEqual::operator()(k, extract(e.value));
207 }
208
209 bool
210 operator()(element const& e, Key const& k) const
211 {
212 return KeyEqual::operator()(extract(e.value), k);
213 }
214
215 bool
216 operator()(element const& lhs, element const& rhs) const
217 {
218 return KeyEqual::operator()(extract(lhs.value), extract(rhs.value));
219 }
220
221 KeyEqual&
223 {
224 return *this;
225 }
226
227 KeyEqual const&
228 key_eq() const
229 {
230 return *this;
231 }
232 };
233
234 using list_type = typename boost::intrusive::
235 make_list<element, boost::intrusive::constant_time_size<false>>::type;
236
237 using cont_type = typename std::conditional<
238 IsMulti,
239 typename boost::intrusive::make_unordered_multiset<
240 element,
241 boost::intrusive::constant_time_size<true>,
242 boost::intrusive::hash<ValueHash>,
243 boost::intrusive::equal<KeyValueEqual>,
244 boost::intrusive::cache_begin<true>>::type,
245 typename boost::intrusive::make_unordered_set<
246 element,
247 boost::intrusive::constant_time_size<true>,
248 boost::intrusive::hash<ValueHash>,
249 boost::intrusive::equal<KeyValueEqual>,
250 boost::intrusive::cache_begin<true>>::type>::type;
251
252 using bucket_type = typename cont_type::bucket_type;
253 using bucket_traits = typename cont_type::bucket_traits;
254
256 Allocator>::template rebind_alloc<element>;
257
259
261 Allocator>::template rebind_alloc<element>;
262
264
266 : private ValueHash,
267 private KeyValueEqual,
268 private beast::detail::empty_base_optimization<ElementAllocator>
269 {
270 public:
271 explicit config_t(clock_type& clock_) : clock(clock_)
272 {
273 }
274
275 config_t(clock_type& clock_, Hash const& hash)
276 : ValueHash(hash), clock(clock_)
277 {
278 }
279
280 config_t(clock_type& clock_, KeyEqual const& keyEqual)
281 : KeyValueEqual(keyEqual), clock(clock_)
282 {
283 }
284
285 config_t(clock_type& clock_, Allocator const& alloc_)
287 , clock(clock_)
288 {
289 }
290
291 config_t(clock_type& clock_, Hash const& hash, KeyEqual const& keyEqual)
292 : ValueHash(hash), KeyValueEqual(keyEqual), clock(clock_)
293 {
294 }
295
296 config_t(clock_type& clock_, Hash const& hash, Allocator const& alloc_)
297 : ValueHash(hash)
299 , clock(clock_)
300 {
301 }
302
304 clock_type& clock_,
305 KeyEqual const& keyEqual,
306 Allocator const& alloc_)
307 : KeyValueEqual(keyEqual)
309 , clock(clock_)
310 {
311 }
312
314 clock_type& clock_,
315 Hash const& hash,
316 KeyEqual const& keyEqual,
317 Allocator const& alloc_)
318 : ValueHash(hash)
319 , KeyValueEqual(keyEqual)
321 , clock(clock_)
322 {
323 }
324
325 config_t(config_t const& other)
326 : ValueHash(other.hash_function())
327 , KeyValueEqual(other.key_eq())
329 ElementAllocatorTraits::select_on_container_copy_construction(
330 other.alloc()))
331 , clock(other.clock)
332 {
333 }
334
335 config_t(config_t const& other, Allocator const& alloc)
336 : ValueHash(other.hash_function())
337 , KeyValueEqual(other.key_eq())
339 , clock(other.clock)
340 {
341 }
342
344 : ValueHash(std::move(other.hash_function()))
345 , KeyValueEqual(std::move(other.key_eq()))
347 std::move(other.alloc()))
348 , clock(other.clock)
349 {
350 }
351
352 config_t(config_t&& other, Allocator const& alloc)
353 : ValueHash(std::move(other.hash_function()))
354 , KeyValueEqual(std::move(other.key_eq()))
356 , clock(other.clock)
357 {
358 }
359
360 config_t&
361 operator=(config_t const& other)
362 {
363 hash_function() = other.hash_function();
364 key_eq() = other.key_eq();
365 alloc() = other.alloc();
366 clock = other.clock;
367 return *this;
368 }
369
370 config_t&
372 {
373 hash_function() = std::move(other.hash_function());
374 key_eq() = std::move(other.key_eq());
375 alloc() = std::move(other.alloc());
376 clock = other.clock;
377 return *this;
378 }
379
380 ValueHash&
382 {
383 return *this;
384 }
385
386 ValueHash const&
388 {
389 return *this;
390 }
391
392 Hash&
394 {
396 }
397
398 Hash const&
400 {
402 }
403
406 {
407 return *this;
408 }
409
410 KeyValueEqual const&
412 {
413 return *this;
414 }
415
416 KeyEqual&
418 {
419 return key_value_equal().key_eq();
420 }
421
422 KeyEqual const&
423 key_eq() const
424 {
425 return key_value_equal().key_eq();
426 }
427
430 {
433 }
434
435 ElementAllocator const&
436 alloc() const
437 {
440 }
441
443 };
444
446 {
447 public:
450 typename std::allocator_traits<Allocator>::template rebind_alloc<
451 bucket_type>>;
452
454 {
455 m_vec.resize(cont_type::suggested_upper_bucket_count(0));
456 }
457
458 Buckets(Allocator const& alloc) : m_max_load_factor(1.f), m_vec(alloc)
459 {
460 m_vec.resize(cont_type::suggested_upper_bucket_count(0));
461 }
462
463 operator bucket_traits()
464 {
465 return bucket_traits(&m_vec[0], m_vec.size());
466 }
467
468 void
470 {
471 m_vec.clear();
472 }
473
476 {
477 return m_vec.max_size();
478 }
479
480 float&
482 {
483 return m_max_load_factor;
484 }
485
486 float const&
488 {
489 return m_max_load_factor;
490 }
491
492 // count is the number of buckets
493 template <class Container>
494 void
495 rehash(size_type count, Container& c)
496 {
497 size_type const size(m_vec.size());
498 if (count == size)
499 return;
500 if (count > m_vec.capacity())
501 {
502 // Need two vectors otherwise we
503 // will destroy non-empty buckets.
505 std::swap(m_vec, vec);
507 c.rehash(bucket_traits(&m_vec[0], m_vec.size()));
508 return;
509 }
510 // Rehash in place.
511 if (count > size)
512 {
513 // This should not reallocate since
514 // we checked capacity earlier.
516 c.rehash(bucket_traits(&m_vec[0], count));
517 return;
518 }
519 // Resize must happen after rehash otherwise
520 // we might destroy non-empty buckets.
521 c.rehash(bucket_traits(&m_vec[0], count));
523 }
524
525 // Resize the buckets to accommodate at least n items.
526 template <class Container>
527 void
528 resize(size_type n, Container& c)
529 {
530 size_type const suggested(
531 cont_type::suggested_upper_bucket_count(n));
532 rehash(suggested, c);
533 }
534
535 private:
538 };
539
540 template <class... Args>
541 element*
542 new_element(Args&&... args)
543 {
544 struct Deleter
545 {
547 Deleter(ElementAllocator& a) : a_(a)
548 {
549 }
550
551 void
552 operator()(element* p)
553 {
554 ElementAllocatorTraits::deallocate(a_.get(), p, 1);
555 }
556 };
557
560 Deleter(m_config.alloc()));
562 m_config.alloc(),
563 p.get(),
564 clock().now(),
565 std::forward<Args>(args)...);
566 return p.release();
567 }
568
569 void
571 {
574 m_config.alloc(), const_cast<element*>(p), 1);
575 }
576
577 void
579 {
580 chronological.list.erase(chronological.list.iterator_to(*p));
581 m_cont.erase(m_cont.iterator_to(*p));
583 }
584
585public:
586 using hasher = Hash;
587 using key_equal = KeyEqual;
588 using allocator_type = Allocator;
594
595 // A set iterator (IsMap==false) is always const
596 // because the elements of a set are immutable.
597 using iterator = beast::detail::
598 aged_container_iterator<!IsMap, typename cont_type::iterator>;
599 using const_iterator = beast::detail::
600 aged_container_iterator<true, typename cont_type::iterator>;
601
602 using local_iterator = beast::detail::
603 aged_container_iterator<!IsMap, typename cont_type::local_iterator>;
604 using const_local_iterator = beast::detail::
605 aged_container_iterator<true, typename cont_type::local_iterator>;
606
607 //--------------------------------------------------------------------------
608 //
609 // Chronological ordered iterators
610 //
611 // "Memberspace"
612 // http://accu.org/index.php/journals/1527
613 //
614 //--------------------------------------------------------------------------
615
617 {
618 public:
619 // A set iterator (IsMap==false) is always const
620 // because the elements of a set are immutable.
621 using iterator = beast::detail::
622 aged_container_iterator<!IsMap, typename list_type::iterator>;
623 using const_iterator = beast::detail::
624 aged_container_iterator<true, typename list_type::iterator>;
626 !IsMap,
627 typename list_type::reverse_iterator>;
628 using const_reverse_iterator = beast::detail::
629 aged_container_iterator<true, typename list_type::reverse_iterator>;
630
633 {
634 return iterator(list.begin());
635 }
636
638 begin() const
639 {
640 return const_iterator(list.begin());
641 }
642
644 cbegin() const
645 {
646 return const_iterator(list.begin());
647 }
648
651 {
652 return iterator(list.end());
653 }
654
656 end() const
657 {
658 return const_iterator(list.end());
659 }
660
662 cend() const
663 {
664 return const_iterator(list.end());
665 }
666
669 {
670 return reverse_iterator(list.rbegin());
671 }
672
674 rbegin() const
675 {
676 return const_reverse_iterator(list.rbegin());
677 }
678
680 crbegin() const
681 {
682 return const_reverse_iterator(list.rbegin());
683 }
684
687 {
688 return reverse_iterator(list.rend());
689 }
690
692 rend() const
693 {
694 return const_reverse_iterator(list.rend());
695 }
696
698 crend() const
699 {
700 return const_reverse_iterator(list.rend());
701 }
702
705 {
706 static_assert(
708 "must be standard layout");
709 return list.iterator_to(*reinterpret_cast<element*>(
710 reinterpret_cast<uint8_t*>(&value) -
711 ((std::size_t)std::addressof(((element*)0)->member))));
712 }
713
715 iterator_to(value_type const& value) const
716 {
717 static_assert(
719 "must be standard layout");
720 return list.iterator_to(*reinterpret_cast<element const*>(
721 reinterpret_cast<uint8_t const*>(&value) -
722 ((std::size_t)std::addressof(((element*)0)->member))));
723 }
724
725 private:
727 {
728 }
729
732
736
737 //--------------------------------------------------------------------------
738 //
739 // Construction
740 //
741 //--------------------------------------------------------------------------
742
744
746
748
750
751 aged_unordered_container(clock_type& clock, Allocator const& alloc);
752
755 Hash const& hash,
756 KeyEqual const& key_eq);
757
760 Hash const& hash,
761 Allocator const& alloc);
762
765 KeyEqual const& key_eq,
766 Allocator const& alloc);
767
770 Hash const& hash,
771 KeyEqual const& key_eq,
772 Allocator const& alloc);
773
774 template <class InputIt>
775 aged_unordered_container(InputIt first, InputIt last, clock_type& clock);
776
777 template <class InputIt>
779 InputIt first,
780 InputIt last,
782 Hash const& hash);
783
784 template <class InputIt>
786 InputIt first,
787 InputIt last,
789 KeyEqual const& key_eq);
790
791 template <class InputIt>
793 InputIt first,
794 InputIt last,
796 Allocator const& alloc);
797
798 template <class InputIt>
800 InputIt first,
801 InputIt last,
803 Hash const& hash,
804 KeyEqual const& key_eq);
805
806 template <class InputIt>
808 InputIt first,
809 InputIt last,
811 Hash const& hash,
812 Allocator const& alloc);
813
814 template <class InputIt>
816 InputIt first,
817 InputIt last,
819 KeyEqual const& key_eq,
820 Allocator const& alloc);
821
822 template <class InputIt>
824 InputIt first,
825 InputIt last,
827 Hash const& hash,
828 KeyEqual const& key_eq,
829 Allocator const& alloc);
830
832
834 aged_unordered_container const& other,
835 Allocator const& alloc);
836
838
841 Allocator const& alloc);
842
846
850 Hash const& hash);
851
855 KeyEqual const& key_eq);
856
860 Allocator const& alloc);
861
865 Hash const& hash,
866 KeyEqual const& key_eq);
867
871 Hash const& hash,
872 Allocator const& alloc);
873
877 KeyEqual const& key_eq,
878 Allocator const& alloc);
879
883 Hash const& hash,
884 KeyEqual const& key_eq,
885 Allocator const& alloc);
886
888
891
894
897
900 {
901 return m_config.alloc();
902 }
903
906 {
907 return m_config.clock;
908 }
909
910 clock_type const&
911 clock() const
912 {
913 return m_config.clock;
914 }
915
916 //--------------------------------------------------------------------------
917 //
918 // Element access (maps)
919 //
920 //--------------------------------------------------------------------------
921
922 template <
923 class K,
924 bool maybe_multi = IsMulti,
925 bool maybe_map = IsMap,
928 at(K const& k);
929
930 template <
931 class K,
932 bool maybe_multi = IsMulti,
933 bool maybe_map = IsMap,
936 at(K const& k) const;
937
938 template <
939 bool maybe_multi = IsMulti,
940 bool maybe_map = IsMap,
943 operator[](Key const& key);
944
945 template <
946 bool maybe_multi = IsMulti,
947 bool maybe_map = IsMap,
950 operator[](Key&& key);
951
952 //--------------------------------------------------------------------------
953 //
954 // Iterators
955 //
956 //--------------------------------------------------------------------------
957
960 {
961 return iterator(m_cont.begin());
962 }
963
965 begin() const
966 {
967 return const_iterator(m_cont.begin());
968 }
969
971 cbegin() const
972 {
973 return const_iterator(m_cont.begin());
974 }
975
978 {
979 return iterator(m_cont.end());
980 }
981
983 end() const
984 {
985 return const_iterator(m_cont.end());
986 }
987
989 cend() const
990 {
991 return const_iterator(m_cont.end());
992 }
993
996 {
997 static_assert(
998 std::is_standard_layout<element>::value, "must be standard layout");
999 return m_cont.iterator_to(*reinterpret_cast<element*>(
1000 reinterpret_cast<uint8_t*>(&value) -
1001 ((std::size_t)std::addressof(((element*)0)->member))));
1002 }
1003
1005 iterator_to(value_type const& value) const
1006 {
1007 static_assert(
1008 std::is_standard_layout<element>::value, "must be standard layout");
1009 return m_cont.iterator_to(*reinterpret_cast<element const*>(
1010 reinterpret_cast<uint8_t const*>(&value) -
1011 ((std::size_t)std::addressof(((element*)0)->member))));
1012 }
1013
1014 //--------------------------------------------------------------------------
1015 //
1016 // Capacity
1017 //
1018 //--------------------------------------------------------------------------
1019
1020 bool
1021 empty() const noexcept
1022 {
1023 return m_cont.empty();
1024 }
1025
1026 size_type
1027 size() const noexcept
1028 {
1029 return m_cont.size();
1030 }
1031
1032 size_type
1033 max_size() const noexcept
1034 {
1035 return m_config.max_size();
1036 }
1037
1038 //--------------------------------------------------------------------------
1039 //
1040 // Modifiers
1041 //
1042 //--------------------------------------------------------------------------
1043
1044 void
1046
1047 // map, set
1048 template <bool maybe_multi = IsMulti>
1049 auto
1050 insert(value_type const& value) ->
1052
1053 // multimap, multiset
1054 template <bool maybe_multi = IsMulti>
1055 auto
1056 insert(value_type const& value) ->
1058
1059 // map, set
1060 template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
1061 auto
1062 insert(value_type&& value) -> typename std::enable_if<
1063 !maybe_multi && !maybe_map,
1065
1066 // multimap, multiset
1067 template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
1068 auto
1069 insert(value_type&& value) ->
1071
1072 // map, set
1073 template <bool maybe_multi = IsMulti>
1075 insert(const_iterator /*hint*/, value_type const& value)
1076 {
1077 // Hint is ignored but we provide the interface so
1078 // callers may use ordered and unordered interchangeably.
1079 return insert(value).first;
1080 }
1081
1082 // multimap, multiset
1083 template <bool maybe_multi = IsMulti>
1085 insert(const_iterator /*hint*/, value_type const& value)
1086 {
1087 // VFALCO TODO The hint could be used to let
1088 // the client order equal ranges
1089 return insert(value);
1090 }
1091
1092 // map, set
1093 template <bool maybe_multi = IsMulti>
1096 {
1097 // Hint is ignored but we provide the interface so
1098 // callers may use ordered and unordered interchangeably.
1099 return insert(std::move(value)).first;
1100 }
1101
1102 // multimap, multiset
1103 template <bool maybe_multi = IsMulti>
1106 {
1107 // VFALCO TODO The hint could be used to let
1108 // the client order equal ranges
1109 return insert(std::move(value));
1110 }
1111
1112 // map, multimap
1113 template <class P, bool maybe_map = IsMap>
1114 typename std::enable_if<
1116 typename std::
1117 conditional<IsMulti, iterator, std::pair<iterator, bool>>::type>::
1118 type
1119 insert(P&& value)
1120 {
1121 return emplace(std::forward<P>(value));
1122 }
1123
1124 // map, multimap
1125 template <class P, bool maybe_map = IsMap>
1126 typename std::enable_if<
1128 typename std::
1129 conditional<IsMulti, iterator, std::pair<iterator, bool>>::type>::
1130 type
1131 insert(const_iterator hint, P&& value)
1132 {
1133 return emplace_hint(hint, std::forward<P>(value));
1134 }
1135
1136 template <class InputIt>
1137 void
1138 insert(InputIt first, InputIt last)
1139 {
1140 insert(
1141 first,
1142 last,
1144 }
1145
1146 void
1148 {
1149 insert(init.begin(), init.end());
1150 }
1151
1152 // set, map
1153 template <bool maybe_multi = IsMulti, class... Args>
1154 auto
1155 emplace(Args&&... args) ->
1157
1158 // multiset, multimap
1159 template <bool maybe_multi = IsMulti, class... Args>
1160 auto
1161 emplace(Args&&... args) ->
1163
1164 // set, map
1165 template <bool maybe_multi = IsMulti, class... Args>
1166 auto
1167 emplace_hint(const_iterator /*hint*/, Args&&... args) ->
1169
1170 // multiset, multimap
1171 template <bool maybe_multi = IsMulti, class... Args>
1173 emplace_hint(const_iterator /*hint*/, Args&&... args)
1174 {
1175 // VFALCO TODO The hint could be used for multi, to let
1176 // the client order equal ranges
1177 return emplace<maybe_multi>(std::forward<Args>(args)...);
1178 }
1179
1180 template <bool is_const, class Iterator>
1183
1184 template <bool is_const, class Iterator>
1189
1190 template <class K>
1191 auto
1192 erase(K const& k) -> size_type;
1193
1194 void
1196
1197 template <bool is_const, class Iterator>
1198 void
1200 {
1201 touch(pos, clock().now());
1202 }
1203
1204 template <class K>
1205 auto
1206 touch(K const& k) -> size_type;
1207
1208 //--------------------------------------------------------------------------
1209 //
1210 // Lookup
1211 //
1212 //--------------------------------------------------------------------------
1213
1214 // VFALCO TODO Respect is_transparent (c++14)
1215 template <class K>
1216 size_type
1217 count(K const& k) const
1218 {
1219 return m_cont.count(
1220 k,
1223 }
1224
1225 // VFALCO TODO Respect is_transparent (c++14)
1226 template <class K>
1227 iterator
1228 find(K const& k)
1229 {
1230 return iterator(m_cont.find(
1231 k,
1234 }
1235
1236 // VFALCO TODO Respect is_transparent (c++14)
1237 template <class K>
1239 find(K const& k) const
1240 {
1241 return const_iterator(m_cont.find(
1242 k,
1245 }
1246
1247 // VFALCO TODO Respect is_transparent (c++14)
1248 template <class K>
1250 equal_range(K const& k)
1251 {
1252 auto const r(m_cont.equal_range(
1253 k,
1256 return std::make_pair(iterator(r.first), iterator(r.second));
1257 }
1258
1259 // VFALCO TODO Respect is_transparent (c++14)
1260 template <class K>
1262 equal_range(K const& k) const
1263 {
1264 auto const r(m_cont.equal_range(
1265 k,
1268 return std::make_pair(
1269 const_iterator(r.first), const_iterator(r.second));
1270 }
1271
1272 //--------------------------------------------------------------------------
1273 //
1274 // Bucket interface
1275 //
1276 //--------------------------------------------------------------------------
1277
1280 {
1281 return local_iterator(m_cont.begin(n));
1282 }
1283
1286 {
1287 return const_local_iterator(m_cont.begin(n));
1288 }
1289
1292 {
1293 return const_local_iterator(m_cont.begin(n));
1294 }
1295
1298 {
1299 return local_iterator(m_cont.end(n));
1300 }
1301
1304 {
1305 return const_local_iterator(m_cont.end(n));
1306 }
1307
1310 {
1311 return const_local_iterator(m_cont.end(n));
1312 }
1313
1314 size_type
1316 {
1317 return m_cont.bucket_count();
1318 }
1319
1320 size_type
1322 {
1323 return m_buck.max_bucket_count();
1324 }
1325
1326 size_type
1328 {
1329 return m_cont.bucket_size(n);
1330 }
1331
1332 size_type
1333 bucket(Key const& k) const
1334 {
1335 XRPL_ASSERT(
1336 bucket_count() != 0,
1337 "beast::detail::aged_unordered_container::bucket : nonzero bucket "
1338 "count");
1339 return m_cont.bucket(k, std::cref(m_config.hash_function()));
1340 }
1341
1342 //--------------------------------------------------------------------------
1343 //
1344 // Hash policy
1345 //
1346 //--------------------------------------------------------------------------
1347
1348 float
1350 {
1351 return size() / static_cast<float>(m_cont.bucket_count());
1352 }
1353
1354 float
1356 {
1357 return m_buck.max_load_factor();
1358 }
1359
1360 void
1362 {
1364 }
1365
1366 void
1368 {
1371 }
1372
1373 void
1375 {
1377 }
1378
1379 //--------------------------------------------------------------------------
1380 //
1381 // Observers
1382 //
1383 //--------------------------------------------------------------------------
1384
1385 hasher const&
1387 {
1388 return m_config.hash_function();
1389 }
1390
1391 key_equal const&
1392 key_eq() const
1393 {
1394 return m_config.key_eq();
1395 }
1396
1397 //--------------------------------------------------------------------------
1398 //
1399 // Comparison
1400 //
1401 //--------------------------------------------------------------------------
1402
1403 // This differs from the standard in that the comparison
1404 // is only done on the key portion of the value type, ignoring
1405 // the mapped type.
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 false,
1418 OtherIsMap,
1419 OtherKey,
1420 OtherT,
1421 OtherDuration,
1422 OtherHash,
1423 KeyEqual,
1424 OtherAllocator> const& other) const;
1425
1426 template <
1427 bool OtherIsMap,
1428 class OtherKey,
1429 class OtherT,
1430 class OtherDuration,
1431 class OtherHash,
1432 class OtherAllocator,
1433 bool maybe_multi = IsMulti>
1436 true,
1437 OtherIsMap,
1438 OtherKey,
1439 OtherT,
1440 OtherDuration,
1441 OtherHash,
1442 KeyEqual,
1443 OtherAllocator> const& other) const;
1444
1445 template <
1446 bool OtherIsMulti,
1447 bool OtherIsMap,
1448 class OtherKey,
1449 class OtherT,
1450 class OtherDuration,
1451 class OtherHash,
1452 class OtherAllocator>
1453 bool
1455 OtherIsMulti,
1456 OtherIsMap,
1457 OtherKey,
1458 OtherT,
1459 OtherDuration,
1460 OtherHash,
1461 KeyEqual,
1462 OtherAllocator> const& other) const
1463 {
1464 return !(this->operator==(other));
1465 }
1466
1467private:
1468 bool
1469 would_exceed(size_type additional) const
1470 {
1471 return size() + additional > bucket_count() * max_load_factor();
1472 }
1473
1474 void
1476 {
1477 if (would_exceed(additional))
1478 m_buck.resize(size() + additional, m_cont);
1479 XRPL_ASSERT(
1481 "beast::detail::aged_unordered_container::maybe_rehash : maximum "
1482 "load factor");
1483 }
1484
1485 // map, set
1486 template <bool maybe_multi = IsMulti>
1487 auto
1490
1491 // multimap, multiset
1492 template <bool maybe_multi = IsMulti>
1493 auto
1496
1497 template <class InputIt>
1498 void
1499 insert_unchecked(InputIt first, InputIt last)
1500 {
1501 for (; first != last; ++first)
1502 insert_unchecked(*first);
1503 }
1504
1505 template <class InputIt>
1506 void
1507 insert(InputIt first, InputIt last, std::input_iterator_tag)
1508 {
1509 for (; first != last; ++first)
1510 insert(*first);
1511 }
1512
1513 template <class InputIt>
1514 void
1515 insert(InputIt first, InputIt last, std::random_access_iterator_tag)
1516 {
1517 auto const n(std::distance(first, last));
1518 maybe_rehash(n);
1519 insert_unchecked(first, last);
1520 }
1521
1522 template <bool is_const, class Iterator>
1523 void
1526 typename clock_type::time_point const& now)
1527 {
1528 auto& e(*pos.iterator());
1529 e.when = now;
1530 chronological.list.erase(chronological.list.iterator_to(e));
1531 chronological.list.push_back(e);
1532 }
1533
1534 template <
1535 bool maybe_propagate = std::allocator_traits<
1536 Allocator>::propagate_on_container_swap::value>
1539 {
1540 std::swap(m_config.key_compare(), other.m_config.key_compare());
1541 std::swap(m_config.alloc(), other.m_config.alloc());
1542 std::swap(m_config.clock, other.m_config.clock);
1543 }
1544
1545 template <
1546 bool maybe_propagate = std::allocator_traits<
1547 Allocator>::propagate_on_container_swap::value>
1550 {
1551 std::swap(m_config.key_compare(), other.m_config.key_compare());
1552 std::swap(m_config.clock, other.m_config.clock);
1553 }
1554
1555private:
1559};
1560
1561//------------------------------------------------------------------------------
1562
1563template <
1564 bool IsMulti,
1565 bool IsMap,
1566 class Key,
1567 class T,
1568 class Clock,
1569 class Hash,
1570 class KeyEqual,
1571 class Allocator>
1573 IsMulti,
1574 IsMap,
1575 Key,
1576 T,
1577 Clock,
1578 Hash,
1579 KeyEqual,
1580 Allocator>::aged_unordered_container(clock_type& clock)
1581 : m_config(clock)
1582 , m_cont(
1583 m_buck,
1584 std::cref(m_config.value_hash()),
1585 std::cref(m_config.key_value_equal()))
1586{
1587}
1588
1589template <
1590 bool IsMulti,
1591 bool IsMap,
1592 class Key,
1593 class T,
1594 class Clock,
1595 class Hash,
1596 class KeyEqual,
1597 class Allocator>
1599 IsMulti,
1600 IsMap,
1601 Key,
1602 T,
1603 Clock,
1604 Hash,
1605 KeyEqual,
1606 Allocator>::aged_unordered_container(clock_type& clock, Hash const& hash)
1607 : m_config(clock, hash)
1608 , m_cont(
1609 m_buck,
1610 std::cref(m_config.value_hash()),
1611 std::cref(m_config.key_value_equal()))
1612{
1613}
1614
1615template <
1616 bool IsMulti,
1617 bool IsMap,
1618 class Key,
1619 class T,
1620 class Clock,
1621 class Hash,
1622 class KeyEqual,
1623 class Allocator>
1625 IsMulti,
1626 IsMap,
1627 Key,
1628 T,
1629 Clock,
1630 Hash,
1631 KeyEqual,
1632 Allocator>::
1633 aged_unordered_container(clock_type& clock, KeyEqual const& key_eq)
1634 : m_config(clock, key_eq)
1635 , m_cont(
1636 m_buck,
1637 std::cref(m_config.value_hash()),
1638 std::cref(m_config.key_value_equal()))
1639{
1640}
1641
1642template <
1643 bool IsMulti,
1644 bool IsMap,
1645 class Key,
1646 class T,
1647 class Clock,
1648 class Hash,
1649 class KeyEqual,
1650 class Allocator>
1652 IsMulti,
1653 IsMap,
1654 Key,
1655 T,
1656 Clock,
1657 Hash,
1658 KeyEqual,
1659 Allocator>::
1660 aged_unordered_container(clock_type& clock, Allocator const& alloc)
1661 : m_config(clock, alloc)
1662 , m_buck(alloc)
1663 , m_cont(
1664 m_buck,
1665 std::cref(m_config.value_hash()),
1666 std::cref(m_config.key_value_equal()))
1667{
1668}
1669
1670template <
1671 bool IsMulti,
1672 bool IsMap,
1673 class Key,
1674 class T,
1675 class Clock,
1676 class Hash,
1677 class KeyEqual,
1678 class Allocator>
1680 IsMulti,
1681 IsMap,
1682 Key,
1683 T,
1684 Clock,
1685 Hash,
1686 KeyEqual,
1687 Allocator>::
1688 aged_unordered_container(
1689 clock_type& clock,
1690 Hash const& hash,
1691 KeyEqual const& key_eq)
1692 : m_config(clock, hash, key_eq)
1693 , m_cont(
1694 m_buck,
1695 std::cref(m_config.value_hash()),
1696 std::cref(m_config.key_value_equal()))
1697{
1698}
1699
1700template <
1701 bool IsMulti,
1702 bool IsMap,
1703 class Key,
1704 class T,
1705 class Clock,
1706 class Hash,
1707 class KeyEqual,
1708 class Allocator>
1710 IsMulti,
1711 IsMap,
1712 Key,
1713 T,
1714 Clock,
1715 Hash,
1716 KeyEqual,
1717 Allocator>::
1718 aged_unordered_container(
1719 clock_type& clock,
1720 Hash const& hash,
1721 Allocator const& alloc)
1722 : m_config(clock, hash, alloc)
1723 , m_buck(alloc)
1724 , m_cont(
1725 m_buck,
1726 std::cref(m_config.value_hash()),
1727 std::cref(m_config.key_value_equal()))
1728{
1729}
1730
1731template <
1732 bool IsMulti,
1733 bool IsMap,
1734 class Key,
1735 class T,
1736 class Clock,
1737 class Hash,
1738 class KeyEqual,
1739 class Allocator>
1741 IsMulti,
1742 IsMap,
1743 Key,
1744 T,
1745 Clock,
1746 Hash,
1747 KeyEqual,
1748 Allocator>::
1749 aged_unordered_container(
1750 clock_type& clock,
1751 KeyEqual const& key_eq,
1752 Allocator const& alloc)
1753 : m_config(clock, key_eq, alloc)
1754 , m_buck(alloc)
1755 , m_cont(
1756 m_buck,
1757 std::cref(m_config.value_hash()),
1758 std::cref(m_config.key_value_equal()))
1759{
1760}
1761
1762template <
1763 bool IsMulti,
1764 bool IsMap,
1765 class Key,
1766 class T,
1767 class Clock,
1768 class Hash,
1769 class KeyEqual,
1770 class Allocator>
1772 IsMulti,
1773 IsMap,
1774 Key,
1775 T,
1776 Clock,
1777 Hash,
1778 KeyEqual,
1779 Allocator>::
1780 aged_unordered_container(
1781 clock_type& clock,
1782 Hash const& hash,
1783 KeyEqual const& key_eq,
1784 Allocator const& alloc)
1785 : m_config(clock, hash, key_eq, alloc)
1786 , m_buck(alloc)
1787 , m_cont(
1788 m_buck,
1789 std::cref(m_config.value_hash()),
1790 std::cref(m_config.key_value_equal()))
1791{
1792}
1793
1794template <
1795 bool IsMulti,
1796 bool IsMap,
1797 class Key,
1798 class T,
1799 class Clock,
1800 class Hash,
1801 class KeyEqual,
1802 class Allocator>
1803template <class InputIt>
1805 IsMulti,
1806 IsMap,
1807 Key,
1808 T,
1809 Clock,
1810 Hash,
1811 KeyEqual,
1812 Allocator>::
1813 aged_unordered_container(InputIt first, InputIt last, clock_type& clock)
1814 : m_config(clock)
1815 , m_cont(
1816 m_buck,
1817 std::cref(m_config.value_hash()),
1818 std::cref(m_config.key_value_equal()))
1819{
1820 insert(first, last);
1821}
1822
1823template <
1824 bool IsMulti,
1825 bool IsMap,
1826 class Key,
1827 class T,
1828 class Clock,
1829 class Hash,
1830 class KeyEqual,
1831 class Allocator>
1832template <class InputIt>
1834 IsMulti,
1835 IsMap,
1836 Key,
1837 T,
1838 Clock,
1839 Hash,
1840 KeyEqual,
1841 Allocator>::
1842 aged_unordered_container(
1843 InputIt first,
1844 InputIt last,
1845 clock_type& clock,
1846 Hash const& hash)
1847 : m_config(clock, hash)
1848 , m_cont(
1849 m_buck,
1850 std::cref(m_config.value_hash()),
1851 std::cref(m_config.key_value_equal()))
1852{
1853 insert(first, last);
1854}
1855
1856template <
1857 bool IsMulti,
1858 bool IsMap,
1859 class Key,
1860 class T,
1861 class Clock,
1862 class Hash,
1863 class KeyEqual,
1864 class Allocator>
1865template <class InputIt>
1867 IsMulti,
1868 IsMap,
1869 Key,
1870 T,
1871 Clock,
1872 Hash,
1873 KeyEqual,
1874 Allocator>::
1875 aged_unordered_container(
1876 InputIt first,
1877 InputIt last,
1878 clock_type& clock,
1879 KeyEqual const& key_eq)
1880 : m_config(clock, key_eq)
1881 , m_cont(
1882 m_buck,
1883 std::cref(m_config.value_hash()),
1884 std::cref(m_config.key_value_equal()))
1885{
1886 insert(first, last);
1887}
1888
1889template <
1890 bool IsMulti,
1891 bool IsMap,
1892 class Key,
1893 class T,
1894 class Clock,
1895 class Hash,
1896 class KeyEqual,
1897 class Allocator>
1898template <class InputIt>
1900 IsMulti,
1901 IsMap,
1902 Key,
1903 T,
1904 Clock,
1905 Hash,
1906 KeyEqual,
1907 Allocator>::
1908 aged_unordered_container(
1909 InputIt first,
1910 InputIt last,
1911 clock_type& clock,
1912 Allocator const& alloc)
1913 : m_config(clock, alloc)
1914 , m_buck(alloc)
1915 , m_cont(
1916 m_buck,
1917 std::cref(m_config.value_hash()),
1918 std::cref(m_config.key_value_equal()))
1919{
1920 insert(first, last);
1921}
1922
1923template <
1924 bool IsMulti,
1925 bool IsMap,
1926 class Key,
1927 class T,
1928 class Clock,
1929 class Hash,
1930 class KeyEqual,
1931 class Allocator>
1932template <class InputIt>
1934 IsMulti,
1935 IsMap,
1936 Key,
1937 T,
1938 Clock,
1939 Hash,
1940 KeyEqual,
1941 Allocator>::
1942 aged_unordered_container(
1943 InputIt first,
1944 InputIt last,
1945 clock_type& clock,
1946 Hash const& hash,
1947 KeyEqual const& key_eq)
1948 : m_config(clock, hash, key_eq)
1949 , m_cont(
1950 m_buck,
1951 std::cref(m_config.value_hash()),
1952 std::cref(m_config.key_value_equal()))
1953{
1954 insert(first, last);
1955}
1956
1957template <
1958 bool IsMulti,
1959 bool IsMap,
1960 class Key,
1961 class T,
1962 class Clock,
1963 class Hash,
1964 class KeyEqual,
1965 class Allocator>
1966template <class InputIt>
1968 IsMulti,
1969 IsMap,
1970 Key,
1971 T,
1972 Clock,
1973 Hash,
1974 KeyEqual,
1975 Allocator>::
1976 aged_unordered_container(
1977 InputIt first,
1978 InputIt last,
1979 clock_type& clock,
1980 Hash const& hash,
1981 Allocator const& alloc)
1982 : m_config(clock, hash, alloc)
1983 , m_buck(alloc)
1984 , m_cont(
1985 m_buck,
1986 std::cref(m_config.value_hash()),
1987 std::cref(m_config.key_value_equal()))
1988{
1989 insert(first, last);
1990}
1991
1992template <
1993 bool IsMulti,
1994 bool IsMap,
1995 class Key,
1996 class T,
1997 class Clock,
1998 class Hash,
1999 class KeyEqual,
2000 class Allocator>
2001template <class InputIt>
2003 IsMulti,
2004 IsMap,
2005 Key,
2006 T,
2007 Clock,
2008 Hash,
2009 KeyEqual,
2010 Allocator>::
2011 aged_unordered_container(
2012 InputIt first,
2013 InputIt last,
2014 clock_type& clock,
2015 KeyEqual const& key_eq,
2016 Allocator const& alloc)
2017 : m_config(clock, key_eq, alloc)
2018 , m_buck(alloc)
2019 , m_cont(
2020 m_buck,
2021 std::cref(m_config.value_hash()),
2022 std::cref(m_config.key_value_equal()))
2023{
2024 insert(first, last);
2025}
2026
2027template <
2028 bool IsMulti,
2029 bool IsMap,
2030 class Key,
2031 class T,
2032 class Clock,
2033 class Hash,
2034 class KeyEqual,
2035 class Allocator>
2036template <class InputIt>
2038 IsMulti,
2039 IsMap,
2040 Key,
2041 T,
2042 Clock,
2043 Hash,
2044 KeyEqual,
2045 Allocator>::
2046 aged_unordered_container(
2047 InputIt first,
2048 InputIt last,
2049 clock_type& clock,
2050 Hash const& hash,
2051 KeyEqual const& key_eq,
2052 Allocator const& alloc)
2053 : m_config(clock, hash, key_eq, alloc)
2054 , m_buck(alloc)
2055 , m_cont(
2056 m_buck,
2057 std::cref(m_config.value_hash()),
2058 std::cref(m_config.key_value_equal()))
2059{
2060 insert(first, last);
2061}
2062
2063template <
2064 bool IsMulti,
2065 bool IsMap,
2066 class Key,
2067 class T,
2068 class Clock,
2069 class Hash,
2070 class KeyEqual,
2071 class Allocator>
2073 IsMulti,
2074 IsMap,
2075 Key,
2076 T,
2077 Clock,
2078 Hash,
2079 KeyEqual,
2080 Allocator>::aged_unordered_container(aged_unordered_container const& other)
2081 : m_config(other.m_config)
2082 , m_buck(m_config.alloc())
2083 , m_cont(
2084 m_buck,
2085 std::cref(m_config.value_hash()),
2086 std::cref(m_config.key_value_equal()))
2087{
2088 insert(other.cbegin(), other.cend());
2089}
2090
2091template <
2092 bool IsMulti,
2093 bool IsMap,
2094 class Key,
2095 class T,
2096 class Clock,
2097 class Hash,
2098 class KeyEqual,
2099 class Allocator>
2101 IsMulti,
2102 IsMap,
2103 Key,
2104 T,
2105 Clock,
2106 Hash,
2107 KeyEqual,
2108 Allocator>::
2109 aged_unordered_container(
2110 aged_unordered_container const& other,
2111 Allocator const& alloc)
2112 : m_config(other.m_config, alloc)
2113 , m_buck(alloc)
2114 , m_cont(
2115 m_buck,
2116 std::cref(m_config.value_hash()),
2117 std::cref(m_config.key_value_equal()))
2118{
2119 insert(other.cbegin(), other.cend());
2120}
2121
2122template <
2123 bool IsMulti,
2124 bool IsMap,
2125 class Key,
2126 class T,
2127 class Clock,
2128 class Hash,
2129 class KeyEqual,
2130 class Allocator>
2132 IsMulti,
2133 IsMap,
2134 Key,
2135 T,
2136 Clock,
2137 Hash,
2138 KeyEqual,
2139 Allocator>::aged_unordered_container(aged_unordered_container&& other)
2140 : m_config(std::move(other.m_config))
2141 , m_buck(std::move(other.m_buck))
2142 , m_cont(std::move(other.m_cont))
2143{
2144 chronological.list = std::move(other.chronological.list);
2145}
2146
2147template <
2148 bool IsMulti,
2149 bool IsMap,
2150 class Key,
2151 class T,
2152 class Clock,
2153 class Hash,
2154 class KeyEqual,
2155 class Allocator>
2157 IsMulti,
2158 IsMap,
2159 Key,
2160 T,
2161 Clock,
2162 Hash,
2163 KeyEqual,
2164 Allocator>::
2165 aged_unordered_container(
2167 Allocator const& alloc)
2168 : m_config(std::move(other.m_config), alloc)
2169 , m_buck(alloc)
2170 , m_cont(
2171 m_buck,
2172 std::cref(m_config.value_hash()),
2173 std::cref(m_config.key_value_equal()))
2174{
2175 insert(other.cbegin(), other.cend());
2176 other.clear();
2177}
2178
2179template <
2180 bool IsMulti,
2181 bool IsMap,
2182 class Key,
2183 class T,
2184 class Clock,
2185 class Hash,
2186 class KeyEqual,
2187 class Allocator>
2189 IsMulti,
2190 IsMap,
2191 Key,
2192 T,
2193 Clock,
2194 Hash,
2195 KeyEqual,
2196 Allocator>::
2197 aged_unordered_container(
2199 clock_type& clock)
2200 : m_config(clock)
2201 , m_cont(
2202 m_buck,
2203 std::cref(m_config.value_hash()),
2204 std::cref(m_config.key_value_equal()))
2205{
2206 insert(init.begin(), init.end());
2207}
2208
2209template <
2210 bool IsMulti,
2211 bool IsMap,
2212 class Key,
2213 class T,
2214 class Clock,
2215 class Hash,
2216 class KeyEqual,
2217 class Allocator>
2219 IsMulti,
2220 IsMap,
2221 Key,
2222 T,
2223 Clock,
2224 Hash,
2225 KeyEqual,
2226 Allocator>::
2227 aged_unordered_container(
2229 clock_type& clock,
2230 Hash const& hash)
2231 : m_config(clock, hash)
2232 , m_cont(
2233 m_buck,
2234 std::cref(m_config.value_hash()),
2235 std::cref(m_config.key_value_equal()))
2236{
2237 insert(init.begin(), init.end());
2238}
2239
2240template <
2241 bool IsMulti,
2242 bool IsMap,
2243 class Key,
2244 class T,
2245 class Clock,
2246 class Hash,
2247 class KeyEqual,
2248 class Allocator>
2250 IsMulti,
2251 IsMap,
2252 Key,
2253 T,
2254 Clock,
2255 Hash,
2256 KeyEqual,
2257 Allocator>::
2258 aged_unordered_container(
2260 clock_type& clock,
2261 KeyEqual const& key_eq)
2262 : m_config(clock, key_eq)
2263 , m_cont(
2264 m_buck,
2265 std::cref(m_config.value_hash()),
2266 std::cref(m_config.key_value_equal()))
2267{
2268 insert(init.begin(), init.end());
2269}
2270
2271template <
2272 bool IsMulti,
2273 bool IsMap,
2274 class Key,
2275 class T,
2276 class Clock,
2277 class Hash,
2278 class KeyEqual,
2279 class Allocator>
2281 IsMulti,
2282 IsMap,
2283 Key,
2284 T,
2285 Clock,
2286 Hash,
2287 KeyEqual,
2288 Allocator>::
2289 aged_unordered_container(
2291 clock_type& clock,
2292 Allocator const& alloc)
2293 : m_config(clock, alloc)
2294 , m_buck(alloc)
2295 , m_cont(
2296 m_buck,
2297 std::cref(m_config.value_hash()),
2298 std::cref(m_config.key_value_equal()))
2299{
2300 insert(init.begin(), init.end());
2301}
2302
2303template <
2304 bool IsMulti,
2305 bool IsMap,
2306 class Key,
2307 class T,
2308 class Clock,
2309 class Hash,
2310 class KeyEqual,
2311 class Allocator>
2313 IsMulti,
2314 IsMap,
2315 Key,
2316 T,
2317 Clock,
2318 Hash,
2319 KeyEqual,
2320 Allocator>::
2321 aged_unordered_container(
2323 clock_type& clock,
2324 Hash const& hash,
2325 KeyEqual const& key_eq)
2326 : m_config(clock, hash, key_eq)
2327 , m_cont(
2328 m_buck,
2329 std::cref(m_config.value_hash()),
2330 std::cref(m_config.key_value_equal()))
2331{
2332 insert(init.begin(), init.end());
2333}
2334
2335template <
2336 bool IsMulti,
2337 bool IsMap,
2338 class Key,
2339 class T,
2340 class Clock,
2341 class Hash,
2342 class KeyEqual,
2343 class Allocator>
2345 IsMulti,
2346 IsMap,
2347 Key,
2348 T,
2349 Clock,
2350 Hash,
2351 KeyEqual,
2352 Allocator>::
2353 aged_unordered_container(
2355 clock_type& clock,
2356 Hash const& hash,
2357 Allocator const& alloc)
2358 : m_config(clock, hash, alloc)
2359 , m_buck(alloc)
2360 , m_cont(
2361 m_buck,
2362 std::cref(m_config.value_hash()),
2363 std::cref(m_config.key_value_equal()))
2364{
2365 insert(init.begin(), init.end());
2366}
2367
2368template <
2369 bool IsMulti,
2370 bool IsMap,
2371 class Key,
2372 class T,
2373 class Clock,
2374 class Hash,
2375 class KeyEqual,
2376 class Allocator>
2378 IsMulti,
2379 IsMap,
2380 Key,
2381 T,
2382 Clock,
2383 Hash,
2384 KeyEqual,
2385 Allocator>::
2386 aged_unordered_container(
2388 clock_type& clock,
2389 KeyEqual const& key_eq,
2390 Allocator const& alloc)
2391 : m_config(clock, key_eq, alloc)
2392 , m_buck(alloc)
2393 , m_cont(
2394 m_buck,
2395 std::cref(m_config.value_hash()),
2396 std::cref(m_config.key_value_equal()))
2397{
2398 insert(init.begin(), init.end());
2399}
2400
2401template <
2402 bool IsMulti,
2403 bool IsMap,
2404 class Key,
2405 class T,
2406 class Clock,
2407 class Hash,
2408 class KeyEqual,
2409 class Allocator>
2411 IsMulti,
2412 IsMap,
2413 Key,
2414 T,
2415 Clock,
2416 Hash,
2417 KeyEqual,
2418 Allocator>::
2419 aged_unordered_container(
2421 clock_type& clock,
2422 Hash const& hash,
2423 KeyEqual const& key_eq,
2424 Allocator const& alloc)
2425 : m_config(clock, hash, key_eq, alloc)
2426 , m_buck(alloc)
2427 , m_cont(
2428 m_buck,
2429 std::cref(m_config.value_hash()),
2430 std::cref(m_config.key_value_equal()))
2431{
2432 insert(init.begin(), init.end());
2433}
2434
2435template <
2436 bool IsMulti,
2437 bool IsMap,
2438 class Key,
2439 class T,
2440 class Clock,
2441 class Hash,
2442 class KeyEqual,
2443 class Allocator>
2445 IsMulti,
2446 IsMap,
2447 Key,
2448 T,
2449 Clock,
2450 Hash,
2451 KeyEqual,
2452 Allocator>::~aged_unordered_container()
2453{
2454 clear();
2455}
2456
2457template <
2458 bool IsMulti,
2459 bool IsMap,
2460 class Key,
2461 class T,
2462 class Clock,
2463 class Hash,
2464 class KeyEqual,
2465 class Allocator>
2466auto
2468 IsMulti,
2469 IsMap,
2470 Key,
2471 T,
2472 Clock,
2473 Hash,
2474 KeyEqual,
2475 Allocator>::operator=(aged_unordered_container const& other)
2477{
2478 if (this != &other)
2479 {
2480 size_type const n(other.size());
2481 clear();
2482 m_config = other.m_config;
2483 m_buck = Buckets(m_config.alloc());
2484 maybe_rehash(n);
2485 insert_unchecked(other.begin(), other.end());
2486 }
2487 return *this;
2488}
2489
2490template <
2491 bool IsMulti,
2492 bool IsMap,
2493 class Key,
2494 class T,
2495 class Clock,
2496 class Hash,
2497 class KeyEqual,
2498 class Allocator>
2499auto
2501 IsMulti,
2502 IsMap,
2503 Key,
2504 T,
2505 Clock,
2506 Hash,
2507 KeyEqual,
2508 Allocator>::operator=(aged_unordered_container&& other)
2510{
2511 size_type const n(other.size());
2512 clear();
2513 m_config = std::move(other.m_config);
2514 m_buck = Buckets(m_config.alloc());
2515 maybe_rehash(n);
2516 insert_unchecked(other.begin(), other.end());
2517 other.clear();
2518 return *this;
2519}
2520
2521template <
2522 bool IsMulti,
2523 bool IsMap,
2524 class Key,
2525 class T,
2526 class Clock,
2527 class Hash,
2528 class KeyEqual,
2529 class Allocator>
2530auto
2532 IsMulti,
2533 IsMap,
2534 Key,
2535 T,
2536 Clock,
2537 Hash,
2538 KeyEqual,
2539 Allocator>::operator=(std::initializer_list<value_type> init)
2541{
2542 clear();
2543 insert(init);
2544 return *this;
2545}
2546
2547//------------------------------------------------------------------------------
2548
2549template <
2550 bool IsMulti,
2551 bool IsMap,
2552 class Key,
2553 class T,
2554 class Clock,
2555 class Hash,
2556 class KeyEqual,
2557 class Allocator>
2558template <class K, bool maybe_multi, bool maybe_map, class>
2561 IsMulti,
2562 IsMap,
2563 Key,
2564 T,
2565 Clock,
2566 Hash,
2567 KeyEqual,
2568 Allocator>::at(K const& k)
2569{
2570 auto const iter(m_cont.find(
2571 k,
2572 std::cref(m_config.hash_function()),
2573 std::cref(m_config.key_value_equal())));
2574 if (iter == m_cont.end())
2575 throw std::out_of_range("key not found");
2576 return iter->value.second;
2577}
2578
2579template <
2580 bool IsMulti,
2581 bool IsMap,
2582 class Key,
2583 class T,
2584 class Clock,
2585 class Hash,
2586 class KeyEqual,
2587 class Allocator>
2588template <class K, bool maybe_multi, bool maybe_map, class>
2591 IsMulti,
2592 IsMap,
2593 Key,
2594 T,
2595 Clock,
2596 Hash,
2597 KeyEqual,
2598 Allocator>::at(K const& k) const
2599{
2600 auto const iter(m_cont.find(
2601 k,
2602 std::cref(m_config.hash_function()),
2603 std::cref(m_config.key_value_equal())));
2604 if (iter == m_cont.end())
2605 throw std::out_of_range("key not found");
2606 return iter->value.second;
2607}
2608
2609template <
2610 bool IsMulti,
2611 bool IsMap,
2612 class Key,
2613 class T,
2614 class Clock,
2615 class Hash,
2616 class KeyEqual,
2617 class Allocator>
2618template <bool maybe_multi, bool maybe_map, class>
2621 IsMulti,
2622 IsMap,
2623 Key,
2624 T,
2625 Clock,
2626 Hash,
2627 KeyEqual,
2628 Allocator>::operator[](Key const& key)
2629{
2630 maybe_rehash(1);
2631 typename cont_type::insert_commit_data d;
2632 auto const result(m_cont.insert_check(
2633 key,
2634 std::cref(m_config.hash_function()),
2635 std::cref(m_config.key_value_equal()),
2636 d));
2637 if (result.second)
2638 {
2639 element* const p(new_element(
2643 m_cont.insert_commit(*p, d);
2644 chronological.list.push_back(*p);
2645 return p->value.second;
2646 }
2647 return result.first->value.second;
2648}
2649
2650template <
2651 bool IsMulti,
2652 bool IsMap,
2653 class Key,
2654 class T,
2655 class Clock,
2656 class Hash,
2657 class KeyEqual,
2658 class Allocator>
2659template <bool maybe_multi, bool maybe_map, class>
2662 IsMulti,
2663 IsMap,
2664 Key,
2665 T,
2666 Clock,
2667 Hash,
2668 KeyEqual,
2669 Allocator>::operator[](Key&& key)
2670{
2671 maybe_rehash(1);
2672 typename cont_type::insert_commit_data d;
2673 auto const result(m_cont.insert_check(
2674 key,
2675 std::cref(m_config.hash_function()),
2676 std::cref(m_config.key_value_equal()),
2677 d));
2678 if (result.second)
2679 {
2680 element* const p(new_element(
2682 std::forward_as_tuple(std::move(key)),
2684 m_cont.insert_commit(*p, d);
2685 chronological.list.push_back(*p);
2686 return p->value.second;
2687 }
2688 return result.first->value.second;
2689}
2690
2691//------------------------------------------------------------------------------
2692
2693template <
2694 bool IsMulti,
2695 bool IsMap,
2696 class Key,
2697 class T,
2698 class Clock,
2699 class Hash,
2700 class KeyEqual,
2701 class Allocator>
2702void
2704 IsMulti,
2705 IsMap,
2706 Key,
2707 T,
2708 Clock,
2709 Hash,
2710 KeyEqual,
2711 Allocator>::clear()
2712{
2713 for (auto iter(chronological.list.begin());
2714 iter != chronological.list.end();)
2715 unlink_and_delete_element(&*iter++);
2716 chronological.list.clear();
2717 m_cont.clear();
2718 m_buck.clear();
2719}
2720
2721// map, set
2722template <
2723 bool IsMulti,
2724 bool IsMap,
2725 class Key,
2726 class T,
2727 class Clock,
2728 class Hash,
2729 class KeyEqual,
2730 class Allocator>
2731template <bool maybe_multi>
2732auto
2734 IsMulti,
2735 IsMap,
2736 Key,
2737 T,
2738 Clock,
2739 Hash,
2740 KeyEqual,
2741 Allocator>::insert(value_type const& value) ->
2743{
2744 maybe_rehash(1);
2745 typename cont_type::insert_commit_data d;
2746 auto const result(m_cont.insert_check(
2747 extract(value),
2748 std::cref(m_config.hash_function()),
2749 std::cref(m_config.key_value_equal()),
2750 d));
2751 if (result.second)
2752 {
2753 element* const p(new_element(value));
2754 auto const iter(m_cont.insert_commit(*p, d));
2755 chronological.list.push_back(*p);
2756 return std::make_pair(iterator(iter), true);
2757 }
2758 return std::make_pair(iterator(result.first), false);
2759}
2760
2761// multimap, multiset
2762template <
2763 bool IsMulti,
2764 bool IsMap,
2765 class Key,
2766 class T,
2767 class Clock,
2768 class Hash,
2769 class KeyEqual,
2770 class Allocator>
2771template <bool maybe_multi>
2772auto
2774 IsMulti,
2775 IsMap,
2776 Key,
2777 T,
2778 Clock,
2779 Hash,
2780 KeyEqual,
2781 Allocator>::insert(value_type const& value) ->
2783{
2784 maybe_rehash(1);
2785 element* const p(new_element(value));
2786 chronological.list.push_back(*p);
2787 auto const iter(m_cont.insert(*p));
2788 return iterator(iter);
2789}
2790
2791// map, set
2792template <
2793 bool IsMulti,
2794 bool IsMap,
2795 class Key,
2796 class T,
2797 class Clock,
2798 class Hash,
2799 class KeyEqual,
2800 class Allocator>
2801template <bool maybe_multi, bool maybe_map>
2802auto
2803aged_unordered_container<
2804 IsMulti,
2805 IsMap,
2806 Key,
2807 T,
2808 Clock,
2809 Hash,
2810 KeyEqual,
2811 Allocator>::insert(value_type&& value) ->
2812 typename std::
2813 enable_if<!maybe_multi && !maybe_map, std::pair<iterator, bool>>::type
2814{
2815 maybe_rehash(1);
2816 typename cont_type::insert_commit_data d;
2817 auto const result(m_cont.insert_check(
2818 extract(value),
2819 std::cref(m_config.hash_function()),
2820 std::cref(m_config.key_value_equal()),
2821 d));
2822 if (result.second)
2823 {
2824 element* const p(new_element(std::move(value)));
2825 auto const iter(m_cont.insert_commit(*p, d));
2826 chronological.list.push_back(*p);
2827 return std::make_pair(iterator(iter), true);
2828 }
2829 return std::make_pair(iterator(result.first), false);
2830}
2831
2832// multimap, multiset
2833template <
2834 bool IsMulti,
2835 bool IsMap,
2836 class Key,
2837 class T,
2838 class Clock,
2839 class Hash,
2840 class KeyEqual,
2841 class Allocator>
2842template <bool maybe_multi, bool maybe_map>
2843auto
2845 IsMulti,
2846 IsMap,
2847 Key,
2848 T,
2849 Clock,
2850 Hash,
2851 KeyEqual,
2852 Allocator>::insert(value_type&& value) ->
2854{
2855 maybe_rehash(1);
2856 element* const p(new_element(std::move(value)));
2857 chronological.list.push_back(*p);
2858 auto const iter(m_cont.insert(*p));
2859 return iterator(iter);
2860}
2861
2862#if 1 // Use insert() instead of insert_check() insert_commit()
2863// set, map
2864template <
2865 bool IsMulti,
2866 bool IsMap,
2867 class Key,
2868 class T,
2869 class Clock,
2870 class Hash,
2871 class KeyEqual,
2872 class Allocator>
2873template <bool maybe_multi, class... Args>
2874auto
2875aged_unordered_container<
2876 IsMulti,
2877 IsMap,
2878 Key,
2879 T,
2880 Clock,
2881 Hash,
2882 KeyEqual,
2883 Allocator>::emplace(Args&&... args) ->
2885{
2886 maybe_rehash(1);
2887 // VFALCO NOTE Its unfortunate that we need to
2888 // construct element here
2889 element* const p(new_element(std::forward<Args>(args)...));
2890 auto const result(m_cont.insert(*p));
2891 if (result.second)
2892 {
2893 chronological.list.push_back(*p);
2894 return std::make_pair(iterator(result.first), true);
2895 }
2896 delete_element(p);
2897 return std::make_pair(iterator(result.first), false);
2898}
2899#else // As original, use insert_check() / insert_commit () pair.
2900// set, map
2901template <
2902 bool IsMulti,
2903 bool IsMap,
2904 class Key,
2905 class T,
2906 class Clock,
2907 class Hash,
2908 class KeyEqual,
2909 class Allocator>
2910template <bool maybe_multi, class... Args>
2911auto
2913 IsMulti,
2914 IsMap,
2915 Key,
2916 T,
2917 Clock,
2918 Hash,
2919 KeyEqual,
2920 Allocator>::emplace(Args&&... args) ->
2922{
2923 maybe_rehash(1);
2924 // VFALCO NOTE Its unfortunate that we need to
2925 // construct element here
2926 element* const p(new_element(std::forward<Args>(args)...));
2927 typename cont_type::insert_commit_data d;
2928 auto const result(m_cont.insert_check(
2929 extract(p->value),
2930 std::cref(m_config.hash_function()),
2931 std::cref(m_config.key_value_equal()),
2932 d));
2933 if (result.second)
2934 {
2935 auto const iter(m_cont.insert_commit(*p, d));
2936 chronological.list.push_back(*p);
2937 return std::make_pair(iterator(iter), true);
2938 }
2939 delete_element(p);
2940 return std::make_pair(iterator(result.first), false);
2941}
2942#endif // 0
2943
2944// multiset, multimap
2945template <
2946 bool IsMulti,
2947 bool IsMap,
2948 class Key,
2949 class T,
2950 class Clock,
2951 class Hash,
2952 class KeyEqual,
2953 class Allocator>
2954template <bool maybe_multi, class... Args>
2955auto
2956aged_unordered_container<
2957 IsMulti,
2958 IsMap,
2959 Key,
2960 T,
2961 Clock,
2962 Hash,
2963 KeyEqual,
2964 Allocator>::emplace(Args&&... args) ->
2966{
2967 maybe_rehash(1);
2968 element* const p(new_element(std::forward<Args>(args)...));
2969 chronological.list.push_back(*p);
2970 auto const iter(m_cont.insert(*p));
2971 return iterator(iter);
2972}
2973
2974// set, map
2975template <
2976 bool IsMulti,
2977 bool IsMap,
2978 class Key,
2979 class T,
2980 class Clock,
2981 class Hash,
2982 class KeyEqual,
2983 class Allocator>
2984template <bool maybe_multi, class... Args>
2985auto
2986aged_unordered_container<
2987 IsMulti,
2988 IsMap,
2989 Key,
2990 T,
2991 Clock,
2992 Hash,
2993 KeyEqual,
2994 Allocator>::emplace_hint(const_iterator /*hint*/, Args&&... args) ->
2996{
2997 maybe_rehash(1);
2998 // VFALCO NOTE Its unfortunate that we need to
2999 // construct element here
3000 element* const p(new_element(std::forward<Args>(args)...));
3001 typename cont_type::insert_commit_data d;
3002 auto const result(m_cont.insert_check(
3003 extract(p->value),
3004 std::cref(m_config.hash_function()),
3005 std::cref(m_config.key_value_equal()),
3006 d));
3007 if (result.second)
3008 {
3009 auto const iter(m_cont.insert_commit(*p, d));
3010 chronological.list.push_back(*p);
3011 return std::make_pair(iterator(iter), true);
3012 }
3013 delete_element(p);
3014 return std::make_pair(iterator(result.first), false);
3015}
3016
3017template <
3018 bool IsMulti,
3019 bool IsMap,
3020 class Key,
3021 class T,
3022 class Clock,
3023 class Hash,
3024 class KeyEqual,
3025 class Allocator>
3026template <bool is_const, class Iterator>
3029 IsMulti,
3030 IsMap,
3031 Key,
3032 T,
3033 Clock,
3034 Hash,
3035 KeyEqual,
3037 pos)
3038{
3039 unlink_and_delete_element(&*((pos++).iterator()));
3041 pos.iterator());
3042}
3043
3044template <
3045 bool IsMulti,
3046 bool IsMap,
3047 class Key,
3048 class T,
3049 class Clock,
3050 class Hash,
3051 class KeyEqual,
3052 class Allocator>
3053template <bool is_const, class Iterator>
3056 IsMulti,
3057 IsMap,
3058 Key,
3059 T,
3060 Clock,
3061 Hash,
3062 KeyEqual,
3063 Allocator>::
3064 erase(
3067{
3068 for (; first != last;)
3069 unlink_and_delete_element(&*((first++).iterator()));
3070
3072 first.iterator());
3073}
3074
3075template <
3076 bool IsMulti,
3077 bool IsMap,
3078 class Key,
3079 class T,
3080 class Clock,
3081 class Hash,
3082 class KeyEqual,
3083 class Allocator>
3084template <class K>
3085auto
3087 IsMulti,
3088 IsMap,
3089 Key,
3090 T,
3091 Clock,
3092 Hash,
3093 KeyEqual,
3094 Allocator>::erase(K const& k) -> size_type
3095{
3096 auto iter(m_cont.find(
3097 k,
3098 std::cref(m_config.hash_function()),
3099 std::cref(m_config.key_value_equal())));
3100 if (iter == m_cont.end())
3101 return 0;
3102 size_type n(0);
3103 for (;;)
3104 {
3105 auto p(&*iter++);
3106 bool const done(m_config(*p, extract(iter->value)));
3107 unlink_and_delete_element(p);
3108 ++n;
3109 if (done)
3110 break;
3111 }
3112 return n;
3113}
3114
3115template <
3116 bool IsMulti,
3117 bool IsMap,
3118 class Key,
3119 class T,
3120 class Clock,
3121 class Hash,
3122 class KeyEqual,
3123 class Allocator>
3124void
3126 IsMulti,
3127 IsMap,
3128 Key,
3129 T,
3130 Clock,
3131 Hash,
3132 KeyEqual,
3133 Allocator>::swap(aged_unordered_container& other) noexcept
3134{
3135 swap_data(other);
3136 std::swap(chronological, other.chronological);
3137 std::swap(m_cont, other.m_cont);
3138}
3139
3140template <
3141 bool IsMulti,
3142 bool IsMap,
3143 class Key,
3144 class T,
3145 class Clock,
3146 class Hash,
3147 class KeyEqual,
3148 class Allocator>
3149template <class K>
3150auto
3152 IsMulti,
3153 IsMap,
3154 Key,
3155 T,
3156 Clock,
3157 Hash,
3158 KeyEqual,
3159 Allocator>::touch(K const& k) -> size_type
3160{
3161 auto const now(clock().now());
3162 size_type n(0);
3163 auto const range(equal_range(k));
3164 for (auto iter : range)
3165 {
3166 touch(iter, now);
3167 ++n;
3168 }
3169 return n;
3170}
3171
3172template <
3173 bool IsMulti,
3174 bool IsMap,
3175 class Key,
3176 class T,
3177 class Clock,
3178 class Hash,
3179 class KeyEqual,
3180 class Allocator>
3181template <
3182 bool OtherIsMap,
3183 class OtherKey,
3184 class OtherT,
3185 class OtherDuration,
3186 class OtherHash,
3187 class OtherAllocator,
3188 bool maybe_multi>
3191 IsMulti,
3192 IsMap,
3193 Key,
3194 T,
3195 Clock,
3196 Hash,
3197 KeyEqual,
3198 Allocator>::
3199operator==(aged_unordered_container<
3200 false,
3201 OtherIsMap,
3202 OtherKey,
3203 OtherT,
3204 OtherDuration,
3205 OtherHash,
3206 KeyEqual,
3207 OtherAllocator> const& other) const
3208{
3209 if (size() != other.size())
3210 return false;
3211 for (auto iter(cbegin()), last(cend()), olast(other.cend()); iter != last;
3212 ++iter)
3213 {
3214 auto oiter(other.find(extract(*iter)));
3215 if (oiter == olast)
3216 return false;
3217 }
3218 return true;
3219}
3220
3221template <
3222 bool IsMulti,
3223 bool IsMap,
3224 class Key,
3225 class T,
3226 class Clock,
3227 class Hash,
3228 class KeyEqual,
3229 class Allocator>
3230template <
3231 bool OtherIsMap,
3232 class OtherKey,
3233 class OtherT,
3234 class OtherDuration,
3235 class OtherHash,
3236 class OtherAllocator,
3237 bool maybe_multi>
3240 IsMulti,
3241 IsMap,
3242 Key,
3243 T,
3244 Clock,
3245 Hash,
3246 KeyEqual,
3247 Allocator>::
3248operator==(aged_unordered_container<
3249 true,
3250 OtherIsMap,
3251 OtherKey,
3252 OtherT,
3253 OtherDuration,
3254 OtherHash,
3255 KeyEqual,
3256 OtherAllocator> const& other) const
3257{
3258 if (size() != other.size())
3259 return false;
3261 for (auto iter(cbegin()), last(cend()); iter != last;)
3262 {
3263 auto const& k(extract(*iter));
3264 auto const eq(equal_range(k));
3265 auto const oeq(other.equal_range(k));
3266#if BEAST_NO_CXX14_IS_PERMUTATION
3267 if (std::distance(eq.first, eq.second) !=
3268 std::distance(oeq.first, oeq.second) ||
3269 !std::is_permutation(eq.first, eq.second, oeq.first))
3270 return false;
3271#else
3272 if (!std::is_permutation(eq.first, eq.second, oeq.first, oeq.second))
3273 return false;
3274#endif
3275 iter = eq.second;
3276 }
3277 return true;
3278}
3279
3280//------------------------------------------------------------------------------
3281
3282// map, set
3283template <
3284 bool IsMulti,
3285 bool IsMap,
3286 class Key,
3287 class T,
3288 class Clock,
3289 class Hash,
3290 class KeyEqual,
3291 class Allocator>
3292template <bool maybe_multi>
3293auto
3295 IsMulti,
3296 IsMap,
3297 Key,
3298 T,
3299 Clock,
3300 Hash,
3301 KeyEqual,
3302 Allocator>::insert_unchecked(value_type const& value) ->
3304{
3305 typename cont_type::insert_commit_data d;
3306 auto const result(m_cont.insert_check(
3307 extract(value),
3308 std::cref(m_config.hash_function()),
3309 std::cref(m_config.key_value_equal()),
3310 d));
3311 if (result.second)
3312 {
3313 element* const p(new_element(value));
3314 auto const iter(m_cont.insert_commit(*p, d));
3315 chronological.list.push_back(*p);
3316 return std::make_pair(iterator(iter), true);
3317 }
3318 return std::make_pair(iterator(result.first), false);
3319}
3320
3321// multimap, multiset
3322template <
3323 bool IsMulti,
3324 bool IsMap,
3325 class Key,
3326 class T,
3327 class Clock,
3328 class Hash,
3329 class KeyEqual,
3330 class Allocator>
3331template <bool maybe_multi>
3332auto
3334 IsMulti,
3335 IsMap,
3336 Key,
3337 T,
3338 Clock,
3339 Hash,
3340 KeyEqual,
3341 Allocator>::insert_unchecked(value_type const& value) ->
3343{
3344 element* const p(new_element(value));
3345 chronological.list.push_back(*p);
3346 auto const iter(m_cont.insert(*p));
3347 return iterator(iter);
3348}
3349
3350//------------------------------------------------------------------------------
3351
3352} // namespace detail
3353
3354//------------------------------------------------------------------------------
3355
3356template <
3357 bool IsMulti,
3358 bool IsMap,
3359 class Key,
3360 class T,
3361 class Clock,
3362 class Hash,
3363 class KeyEqual,
3364 class Allocator>
3366 IsMulti,
3367 IsMap,
3368 Key,
3369 T,
3370 Clock,
3371 Hash,
3372 KeyEqual,
3373 Allocator>> : std::true_type
3374{
3375 explicit is_aged_container() = default;
3376};
3377
3378// Free functions
3379
3380template <
3381 bool IsMulti,
3382 bool IsMap,
3383 class Key,
3384 class T,
3385 class Clock,
3386 class Hash,
3387 class KeyEqual,
3388 class Allocator>
3389void
3392 IsMulti,
3393 IsMap,
3394 Key,
3395 T,
3396 Clock,
3397 Hash,
3398 KeyEqual,
3399 Allocator>& lhs,
3401 IsMulti,
3402 IsMap,
3403 Key,
3404 T,
3405 Clock,
3406 Hash,
3407 KeyEqual,
3408 Allocator>& rhs) noexcept
3409{
3410 lhs.swap(rhs);
3411}
3412
3414template <
3415 bool IsMulti,
3416 bool IsMap,
3417 class Key,
3418 class T,
3419 class Clock,
3420 class Hash,
3421 class KeyEqual,
3422 class Allocator,
3423 class Rep,
3424 class Period>
3428 IsMulti,
3429 IsMap,
3430 Key,
3431 T,
3432 Clock,
3433 Hash,
3434 KeyEqual,
3435 Allocator>& c,
3436 std::chrono::duration<Rep, Period> const& age) noexcept
3437{
3438 std::size_t n(0);
3439 auto const expired(c.clock().now() - age);
3440 for (auto iter(c.chronological.cbegin());
3441 iter != c.chronological.cend() && iter.when() <= expired;)
3442 {
3443 iter = c.erase(iter);
3444 ++n;
3445 }
3446 return n;
3447}
3448
3449} // namespace beast
3450
3451#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)
typename cont_type::bucket_type bucket_type
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)
typename clock_type::time_point time_point
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)
void insert(InputIt first, InputIt last)
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 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)