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