20 #ifndef BEAST_CONTAINER_DETAIL_AGED_UNORDERED_CONTAINER_H_INCLUDED
21 #define BEAST_CONTAINER_DETAIL_AGED_UNORDERED_CONTAINER_H_INCLUDED
23 #include <ripple/beast/clock/abstract_clock.h>
24 #include <ripple/beast/container/aged_container.h>
25 #include <ripple/beast/container/detail/aged_associative_container.h>
26 #include <ripple/beast/container/detail/aged_container_iterator.h>
27 #include <ripple/beast/container/detail/empty_base_optimization.h>
28 #include <boost/intrusive/list.hpp>
29 #include <boost/intrusive/unordered_set.hpp>
51 #ifndef BEAST_NO_CXX14_IS_PERMUTATION
52 #define BEAST_NO_CXX14_IS_PERMUTATION 1
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>>
232 using list_type =
typename boost::intrusive::
233 make_list<element, boost::intrusive::constant_time_size<false>>::type;
237 typename boost::intrusive::make_unordered_multiset<
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<
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;
254 Allocator>::template rebind_alloc<element>;
259 Allocator>::template rebind_alloc<element>;
303 KeyEqual
const& keyEqual,
304 Allocator
const& alloc_)
314 KeyEqual
const& keyEqual,
315 Allocator
const& alloc_)
372 key_eq() = std::move(other.key_eq());
373 alloc() = std::move(other.alloc());
453 m_vec.
resize(cont_type::suggested_upper_bucket_count(0));
458 m_vec.
resize(cont_type::suggested_upper_bucket_count(0));
491 template <
class Container>
524 template <
class Container>
529 cont_type::suggested_upper_bucket_count(n));
538 template <
class... Args>
550 operator()(element* p)
563 std::forward<Args>(args)...);
596 aged_container_iterator<!IsMap, typename cont_type::iterator>;
598 aged_container_iterator<true, typename cont_type::iterator>;
601 aged_container_iterator<!IsMap, typename cont_type::local_iterator>;
603 aged_container_iterator<true, typename cont_type::local_iterator>;
620 aged_container_iterator<!IsMap, typename list_type::iterator>;
622 aged_container_iterator<true, typename list_type::iterator>;
625 typename list_type::reverse_iterator>;
627 aged_container_iterator<true, typename list_type::reverse_iterator>;
706 "must be standard layout");
707 return list.iterator_to(*
reinterpret_cast<element*
>(
708 reinterpret_cast<uint8_t*
>(&value) -
717 "must be standard layout");
718 return list.iterator_to(*
reinterpret_cast<element const*
>(
719 reinterpret_cast<uint8_t const*
>(&value) -
759 Allocator
const& alloc);
764 Allocator
const& alloc);
770 Allocator
const& alloc);
772 template <
class InputIt>
775 template <
class InputIt>
782 template <
class InputIt>
789 template <
class InputIt>
794 Allocator
const& alloc);
796 template <
class InputIt>
804 template <
class InputIt>
810 Allocator
const& alloc);
812 template <
class InputIt>
818 Allocator
const& alloc);
820 template <
class InputIt>
827 Allocator
const& alloc);
833 Allocator
const& alloc);
839 Allocator
const& alloc);
858 Allocator
const& alloc);
870 Allocator
const& alloc);
876 Allocator
const& alloc);
883 Allocator
const& alloc);
922 bool maybe_multi = IsMulti,
923 bool maybe_map = IsMap,
930 bool maybe_multi = IsMulti,
931 bool maybe_map = IsMap,
934 at(K
const& k)
const;
937 bool maybe_multi = IsMulti,
938 bool maybe_map = IsMap,
944 bool maybe_multi = IsMulti,
945 bool maybe_map = IsMap,
997 return m_cont.iterator_to(*
reinterpret_cast<element*
>(
998 reinterpret_cast<uint8_t*
>(&value) -
1007 return m_cont.iterator_to(*
reinterpret_cast<element const*
>(
1008 reinterpret_cast<uint8_t const*
>(&value) -
1046 template <
bool maybe_multi = IsMulti>
1052 template <
bool maybe_multi = IsMulti>
1058 template <
bool maybe_multi = IsMulti,
bool maybe_map = IsMap>
1061 enable_if<!maybe_multi && !maybe_map, std::pair<iterator, bool>>::type;
1064 template <
bool maybe_multi = IsMulti,
bool maybe_map = IsMap>
1070 template <
bool maybe_multi = IsMulti>
1076 return insert(value).first;
1080 template <
bool maybe_multi = IsMulti>
1090 template <
bool maybe_multi = IsMulti>
1096 return insert(std::move(value)).first;
1100 template <
bool maybe_multi = IsMulti>
1106 return insert(std::move(value));
1110 template <
class P,
bool maybe_map = IsMap>
1114 conditional<IsMulti, iterator, std::pair<iterator, bool>>::type>::
1118 return emplace(std::forward<P>(value));
1122 template <
class P,
bool maybe_map = IsMap>
1126 conditional<IsMulti, iterator, std::pair<iterator, bool>>::type>::
1133 template <
class InputIt>
1150 template <
bool maybe_multi = IsMulti,
class... Args>
1156 template <
bool maybe_multi = IsMulti,
class... Args>
1162 template <
bool maybe_multi = IsMulti,
class... Args>
1168 template <
bool maybe_multi = IsMulti,
class... Args>
1174 return emplace<maybe_multi>(std::forward<Args>(args)...);
1177 template <
bool is_const,
class Iterator>
1181 template <
bool is_const,
class Iterator>
1197 template <
bool is_const,
class Iterator>
1252 auto const r(
m_cont.equal_range(
1264 auto const r(
m_cont.equal_range(
1317 return m_cont.bucket_count();
1329 return m_cont.bucket_size(n);
1348 return size() /
static_cast<float>(
m_cont.bucket_count());
1408 class OtherDuration,
1410 class OtherAllocator,
1411 bool maybe_multi = IsMulti>
1421 OtherAllocator>
const& other)
const;
1427 class OtherDuration,
1429 class OtherAllocator,
1430 bool maybe_multi = IsMulti>
1440 OtherAllocator>
const& other)
const;
1447 class OtherDuration,
1449 class OtherAllocator>
1459 OtherAllocator>
const& other)
const
1480 template <
bool maybe_multi = IsMulti>
1486 template <
bool maybe_multi = IsMulti>
1491 template <
class InputIt>
1495 for (; first != last; ++first)
1499 template <
class InputIt>
1503 for (; first != last; ++first)
1507 template <
class InputIt>
1516 template <
bool is_const,
class Iterator>
1530 Allocator>::propagate_on_container_swap::value>
1541 Allocator>::propagate_on_container_swap::value>
1578 std::cref(m_config.value_hash()),
1579 std::cref(m_config.key_value_equal()))
1601 : m_config(clock, hash)
1604 std::cref(m_config.value_hash()),
1605 std::cref(m_config.key_value_equal()))
1627 aged_unordered_container(
clock_type& clock, KeyEqual
const& key_eq)
1628 : m_config(clock, key_eq)
1631 std::cref(m_config.value_hash()),
1632 std::cref(m_config.key_value_equal()))
1654 aged_unordered_container(
clock_type& clock, Allocator
const& alloc)
1655 : m_config(clock, alloc)
1659 std::cref(m_config.value_hash()),
1660 std::cref(m_config.key_value_equal()))
1682 aged_unordered_container(
1685 KeyEqual
const& key_eq)
1686 : m_config(clock, hash, key_eq)
1689 std::cref(m_config.value_hash()),
1690 std::cref(m_config.key_value_equal()))
1712 aged_unordered_container(
1715 Allocator
const& alloc)
1716 : m_config(clock, hash, alloc)
1720 std::cref(m_config.value_hash()),
1721 std::cref(m_config.key_value_equal()))
1743 aged_unordered_container(
1745 KeyEqual
const& key_eq,
1746 Allocator
const& alloc)
1747 : m_config(clock, key_eq, alloc)
1751 std::cref(m_config.value_hash()),
1752 std::cref(m_config.key_value_equal()))
1774 aged_unordered_container(
1777 KeyEqual
const& key_eq,
1778 Allocator
const& alloc)
1779 : m_config(clock, hash, key_eq, alloc)
1783 std::cref(m_config.value_hash()),
1784 std::cref(m_config.key_value_equal()))
1797 template <
class InputIt>
1807 aged_unordered_container(InputIt first, InputIt last,
clock_type& clock)
1811 std::cref(m_config.value_hash()),
1812 std::cref(m_config.key_value_equal()))
1814 insert(first, last);
1826 template <
class InputIt>
1836 aged_unordered_container(
1841 : m_config(clock, hash)
1844 std::cref(m_config.value_hash()),
1845 std::cref(m_config.key_value_equal()))
1847 insert(first, last);
1859 template <
class InputIt>
1869 aged_unordered_container(
1873 KeyEqual
const& key_eq)
1874 : m_config(clock, key_eq)
1877 std::cref(m_config.value_hash()),
1878 std::cref(m_config.key_value_equal()))
1880 insert(first, last);
1892 template <
class InputIt>
1902 aged_unordered_container(
1906 Allocator
const& alloc)
1907 : m_config(clock, alloc)
1911 std::cref(m_config.value_hash()),
1912 std::cref(m_config.key_value_equal()))
1914 insert(first, last);
1926 template <
class InputIt>
1936 aged_unordered_container(
1941 KeyEqual
const& key_eq)
1942 : m_config(clock, hash, key_eq)
1945 std::cref(m_config.value_hash()),
1946 std::cref(m_config.key_value_equal()))
1948 insert(first, last);
1960 template <
class InputIt>
1970 aged_unordered_container(
1975 Allocator
const& alloc)
1976 : m_config(clock, hash, alloc)
1980 std::cref(m_config.value_hash()),
1981 std::cref(m_config.key_value_equal()))
1983 insert(first, last);
1995 template <
class InputIt>
2005 aged_unordered_container(
2009 KeyEqual
const& key_eq,
2010 Allocator
const& alloc)
2011 : m_config(clock, key_eq, alloc)
2015 std::cref(m_config.value_hash()),
2016 std::cref(m_config.key_value_equal()))
2018 insert(first, last);
2030 template <
class InputIt>
2040 aged_unordered_container(
2045 KeyEqual
const& key_eq,
2046 Allocator
const& alloc)
2047 : m_config(clock, hash, key_eq, alloc)
2051 std::cref(m_config.value_hash()),
2052 std::cref(m_config.key_value_equal()))
2054 insert(first, last);
2075 : m_config(other.m_config)
2076 , m_buck(m_config.alloc())
2079 std::cref(m_config.value_hash()),
2080 std::cref(m_config.key_value_equal()))
2103 aged_unordered_container(
2105 Allocator
const& alloc)
2106 : m_config(other.m_config, alloc)
2110 std::cref(m_config.value_hash()),
2111 std::cref(m_config.key_value_equal()))
2134 : m_config(
std::move(other.m_config))
2135 , m_buck(
std::move(other.m_buck))
2136 , m_cont(
std::move(other.m_cont))
2138 chronological.list = std::move(other.chronological.list);
2159 aged_unordered_container(
2161 Allocator
const& alloc)
2162 : m_config(
std::move(other.m_config), alloc)
2166 std::cref(m_config.value_hash()),
2167 std::cref(m_config.key_value_equal()))
2169 insert(other.cbegin(), other.cend());
2191 aged_unordered_container(
2197 std::cref(m_config.value_hash()),
2198 std::cref(m_config.key_value_equal()))
2221 aged_unordered_container(
2225 : m_config(clock, hash)
2228 std::cref(m_config.value_hash()),
2229 std::cref(m_config.key_value_equal()))
2252 aged_unordered_container(
2255 KeyEqual
const& key_eq)
2256 : m_config(clock, key_eq)
2259 std::cref(m_config.value_hash()),
2260 std::cref(m_config.key_value_equal()))
2283 aged_unordered_container(
2286 Allocator
const& alloc)
2287 : m_config(clock, alloc)
2291 std::cref(m_config.value_hash()),
2292 std::cref(m_config.key_value_equal()))
2315 aged_unordered_container(
2319 KeyEqual
const& key_eq)
2320 : m_config(clock, hash, key_eq)
2323 std::cref(m_config.value_hash()),
2324 std::cref(m_config.key_value_equal()))
2347 aged_unordered_container(
2351 Allocator
const& alloc)
2352 : m_config(clock, hash, alloc)
2356 std::cref(m_config.value_hash()),
2357 std::cref(m_config.key_value_equal()))
2380 aged_unordered_container(
2383 KeyEqual
const& key_eq,
2384 Allocator
const& alloc)
2385 : m_config(clock, key_eq, alloc)
2389 std::cref(m_config.value_hash()),
2390 std::cref(m_config.key_value_equal()))
2413 aged_unordered_container(
2417 KeyEqual
const& key_eq,
2418 Allocator
const& alloc)
2419 : m_config(clock, hash, key_eq, alloc)
2423 std::cref(m_config.value_hash()),
2424 std::cref(m_config.key_value_equal()))
2446 Allocator>::~aged_unordered_container()
2476 m_config = other.m_config;
2477 m_buck = Buckets(m_config.alloc());
2479 insert_unchecked(other.begin(), other.end());
2507 m_config = std::move(other.m_config);
2508 m_buck = Buckets(m_config.alloc());
2510 insert_unchecked(other.begin(), other.end());
2552 template <
class K,
bool maybe_multi,
bool maybe_map,
class>
2562 Allocator>::at(K
const& k)
2564 auto const iter(m_cont.find(
2567 std::cref(m_config.key_value_equal())));
2568 if (iter == m_cont.end())
2570 return iter->value.second;
2582 template <
class K,
bool maybe_multi,
bool maybe_map,
class>
2592 Allocator>::at(K
const& k)
const
2594 auto const iter(m_cont.find(
2597 std::cref(m_config.key_value_equal())));
2598 if (iter == m_cont.end())
2600 return iter->value.second;
2612 template <
bool maybe_multi,
bool maybe_map,
class>
2622 Allocator>::operator[](Key
const& key)
2625 typename cont_type::insert_commit_data d;
2626 auto const result(m_cont.insert_check(
2633 element*
const p(new_element(
2634 std::piecewise_construct,
2637 m_cont.insert_commit(*p, d);
2638 chronological.list.push_back(*p);
2639 return p->value.second;
2641 return result.first->value.second;
2653 template <
bool maybe_multi,
bool maybe_map,
class>
2663 Allocator>::operator[](Key&& key)
2666 typename cont_type::insert_commit_data d;
2667 auto const result(m_cont.insert_check(
2674 element*
const p(new_element(
2675 std::piecewise_construct,
2678 m_cont.insert_commit(*p, d);
2679 chronological.list.push_back(*p);
2680 return p->value.second;
2682 return result.first->value.second;
2707 for (
auto iter(chronological.list.begin());
2708 iter != chronological.list.end();)
2709 unlink_and_delete_element(&*iter++);
2710 chronological.list.clear();
2725 template <
bool maybe_multi>
2739 typename cont_type::insert_commit_data d;
2740 auto const result(m_cont.insert_check(
2747 element*
const p(new_element(value));
2748 auto const iter(m_cont.insert_commit(*p, d));
2749 chronological.list.push_back(*p);
2765 template <
bool maybe_multi>
2775 Allocator>::insert(value_type
const& value) ->
2779 element*
const p(new_element(value));
2780 chronological.list.push_back(*p);
2781 auto const iter(m_cont.insert(*p));
2782 return iterator(iter);
2795 template <
bool maybe_multi,
bool maybe_map>
2797 aged_unordered_container<
2806 enable_if<!maybe_multi && !maybe_map, std::pair<iterator, bool>>::type
2809 typename cont_type::insert_commit_data d;
2810 auto const result(m_cont.insert_check(
2817 element*
const p(new_element(std::move(value)));
2818 auto const iter(m_cont.insert_commit(*p, d));
2819 chronological.list.push_back(*p);
2835 template <
bool maybe_multi,
bool maybe_map>
2845 Allocator>::insert(value_type&& value) ->
2849 element*
const p(new_element(std::move(value)));
2850 chronological.list.push_back(*p);
2851 auto const iter(m_cont.insert(*p));
2852 return iterator(iter);
2855 #if 1 // Use insert() instead of insert_check() insert_commit()
2866 template <
bool maybe_multi,
class... Args>
2868 aged_unordered_container<
2876 Allocator>::emplace(Args&&... args) ->
2882 element*
const p(new_element(std::forward<Args>(args)...));
2883 auto const result(m_cont.insert(*p));
2886 chronological.list.push_back(*p);
2892 #else // As original, use insert_check() / insert_commit () pair.
2903 template <
bool maybe_multi,
class... Args>
2913 Allocator>::emplace(Args&&... args) ->
2919 element*
const p(new_element(std::forward<Args>(args)...));
2920 typename cont_type::insert_commit_data d;
2921 auto const result(m_cont.insert_check(
2928 auto const iter(m_cont.insert_commit(*p, d));
2929 chronological.list.push_back(*p);
2947 template <
bool maybe_multi,
class... Args>
2949 aged_unordered_container<
2957 Allocator>::emplace(Args&&... args) ->
2961 element*
const p(new_element(std::forward<Args>(args)...));
2962 chronological.list.push_back(*p);
2963 auto const iter(m_cont.insert(*p));
2964 return iterator(iter);
2977 template <
bool maybe_multi,
class... Args>
2979 aged_unordered_container<
2993 element*
const p(new_element(std::forward<Args>(args)...));
2994 typename cont_type::insert_commit_data d;
2995 auto const result(m_cont.insert_check(
3002 auto const iter(m_cont.insert_commit(*p, d));
3003 chronological.list.push_back(*p);
3019 template <
bool is_const,
class Iterator>
3032 unlink_and_delete_element(&*((pos++).
iterator()));
3046 template <
bool is_const,
class Iterator>
3061 for (; first != last;)
3062 unlink_and_delete_element(&*((first++).
iterator()));
3131 std::swap(chronological, other.chronological);
3156 auto const now(clock().now());
3158 auto const range(equal_range(k));
3159 for (
auto iter : range)
3180 class OtherDuration,
3182 class OtherAllocator,
3202 OtherAllocator>
const& other)
const
3204 if (size() != other.size())
3206 for (
auto iter(cbegin()), last(cend()), olast(other.cend()); iter != last;
3209 auto oiter(other.find(extract(*iter)));
3229 class OtherDuration,
3231 class OtherAllocator,
3251 OtherAllocator>
const& other)
const
3253 if (size() != other.size())
3256 for (
auto iter(cbegin()), last(cend()); iter != last;)
3258 auto const& k(extract(*iter));
3259 auto const eq(equal_range(k));
3260 auto const oeq(other.equal_range(k));
3261 #if BEAST_NO_CXX14_IS_PERMUTATION
3287 template <
bool maybe_multi>
3300 typename cont_type::insert_commit_data d;
3301 auto const result(m_cont.insert_check(
3308 element*
const p(new_element(value));
3309 auto const iter(m_cont.insert_commit(*p, d));
3310 chronological.list.push_back(*p);
3326 template <
bool maybe_multi>
3336 Allocator>::insert_unchecked(value_type
const& value) ->
3339 element*
const p(new_element(value));
3340 chronological.list.push_back(*p);
3341 auto const iter(m_cont.insert(*p));
3342 return iterator(iter);
3403 Allocator>& rhs) noexcept
3434 auto const expired(c.clock().now() - age);
3435 for (
auto iter(c.chronological.cbegin());
3436 iter != c.chronological.cend() && iter.when() <= expired;)
3438 iter = c.erase(iter);