20#ifndef BEAST_CONTAINER_DETAIL_AGED_ORDERED_CONTAINER_H_INCLUDED
21#define BEAST_CONTAINER_DETAIL_AGED_ORDERED_CONTAINER_H_INCLUDED
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/set.hpp>
30#include <boost/version.hpp>
109 : boost::intrusive::set_base_hook<
110 boost::intrusive::link_mode<boost::intrusive::normal_link>>,
111 boost::intrusive::list_base_hook<
112 boost::intrusive::link_mode<boost::intrusive::normal_link>>
158 return Compare::operator()(lhs.first, rhs.first);
224 make_list<element, boost::intrusive::constant_time_size<false>>::type;
228 typename boost::intrusive::make_multiset<
230 boost::intrusive::constant_time_size<true>,
231 boost::intrusive::compare<KeyValueCompare>>::type,
232 typename boost::intrusive::make_set<
234 boost::intrusive::constant_time_size<true>,
235 boost::intrusive::compare<KeyValueCompare>>::type>::type;
238 Allocator>::template rebind_alloc<element>;
265 Allocator
const& alloc_)
318 compare() = std::move(other.compare());
319 alloc() = std::move(other.alloc());
365 template <
class... Args>
379 ElementAllocatorTraits::deallocate(a_.
get(), p, 1);
390 std::forward<Args>(args)...);
424 aged_container_iterator<!IsMap, typename cont_type::iterator>;
426 aged_container_iterator<true, typename cont_type::iterator>;
428 aged_container_iterator<!IsMap, typename cont_type::reverse_iterator>;
430 aged_container_iterator<true, typename cont_type::reverse_iterator>;
447 aged_container_iterator<!IsMap, typename list_type::iterator>;
449 aged_container_iterator<true, typename list_type::iterator>;
452 typename list_type::reverse_iterator>;
454 aged_container_iterator<true, typename list_type::reverse_iterator>;
533 "must be standard layout");
534 return list.iterator_to(*
reinterpret_cast<element*
>(
535 reinterpret_cast<uint8_t*
>(&value) -
544 "must be standard layout");
545 return list.iterator_to(*
reinterpret_cast<element const*
>(
546 reinterpret_cast<uint8_t const*
>(&value) -
579 Allocator
const& alloc);
581 template <
class InputIt>
584 template <
class InputIt>
589 Compare
const& comp);
591 template <
class InputIt>
596 Allocator
const& alloc);
598 template <
class InputIt>
604 Allocator
const& alloc);
610 Allocator
const& alloc);
616 Allocator
const& alloc);
625 Compare
const& comp);
630 Allocator
const& alloc);
636 Allocator
const& alloc);
675 bool maybe_multi = IsMulti,
676 bool maybe_map = IsMap,
683 bool maybe_multi = IsMulti,
684 bool maybe_map = IsMap,
687 at(K
const& k)
const;
690 bool maybe_multi = IsMulti,
691 bool maybe_map = IsMap,
697 bool maybe_multi = IsMulti,
698 bool maybe_map = IsMap,
787 reinterpret_cast<uint8_t*
>(&value) -
797 reinterpret_cast<uint8_t const*
>(&value) -
835 template <
bool maybe_multi = IsMulti>
841 template <
bool maybe_multi = IsMulti>
847 template <
bool maybe_multi = IsMulti,
bool maybe_map = IsMap>
850 !maybe_multi && !maybe_map,
854 template <
bool maybe_multi = IsMulti,
bool maybe_map = IsMap>
862 template <
bool maybe_multi = IsMulti>
868 template <
bool maybe_multi = IsMulti>
877 template <
bool maybe_multi = IsMulti>
883 template <
bool maybe_multi = IsMulti>
888 return insert(std::move(value));
892 template <
class P,
bool maybe_map = IsMap>
896 conditional<IsMulti, iterator, std::pair<iterator, bool>>::type>::
900 return emplace(std::forward<P>(value));
904 template <
class P,
bool maybe_map = IsMap>
908 conditional<IsMulti, iterator, std::pair<iterator, bool>>::type>::
915 template <
class InputIt>
919 for (; first != last; ++first)
930 template <
bool maybe_multi = IsMulti,
class... Args>
936 template <
bool maybe_multi = IsMulti,
class... Args>
942 template <
bool maybe_multi = IsMulti,
class... Args>
948 template <
bool maybe_multi = IsMulti,
class... Args>
953 return emplace<maybe_multi>(std::forward<Args>(args)...);
1118 class OtherDuration,
1119 class OtherAllocator>
1128 OtherAllocator>
const& other)
const;
1134 class OtherDuration,
1135 class OtherAllocator>
1144 OtherAllocator>
const& other)
const
1153 class OtherDuration,
1154 class OtherAllocator>
1163 OtherAllocator>
const& other)
const
1167 cbegin(),
cend(), other.cbegin(), other.cend(), comp);
1174 class OtherDuration,
1175 class OtherAllocator>
1184 OtherAllocator>
const& other)
const
1186 return !(other < *
this);
1193 class OtherDuration,
1194 class OtherAllocator>
1203 OtherAllocator>
const& other)
const
1205 return other < *
this;
1212 class OtherDuration,
1213 class OtherAllocator>
1222 OtherAllocator>
const& other)
const
1224 return !(*
this < other);
1240 Allocator>::propagate_on_container_swap::value>
1246 Allocator>::propagate_on_container_swap::value>
1281 : m_config(clock, comp), m_cont(comp)
1295 : m_config(clock, alloc)
1310 Compare
const& comp,
1311 Allocator
const& alloc)
1312 : m_config(clock, comp, alloc), m_cont(comp)
1324template <
class InputIt>
1340template <
class InputIt>
1346 Compare
const& comp)
1347 : m_config(clock, comp), m_cont(comp)
1360template <
class InputIt>
1366 Allocator
const& alloc)
1367 : m_config(clock, alloc)
1380template <
class InputIt>
1386 Compare
const& comp,
1387 Allocator
const& alloc)
1388 : m_config(clock, comp, alloc), m_cont(comp)
1403 : m_config(other.m_config)
1404#if BOOST_VERSION >= 108000
1405 , m_cont(other.m_cont.get_comp())
1407 , m_cont(other.m_cont.comp())
1424 Allocator
const& alloc)
1425 : m_config(other.m_config, alloc)
1426#if BOOST_VERSION >= 108000
1427 , m_cont(other.m_cont.get_comp())
1429 , m_cont(other.m_cont.comp())
1445 : m_config(
std::move(other.m_config)), m_cont(
std::move(other.m_cont))
1461 Allocator
const& alloc)
1462 : m_config(
std::move(other.m_config), alloc)
1463#if BOOST_VERSION >= 108000
1464 , m_cont(
std::move(other.m_cont.get_comp()))
1466 , m_cont(
std::move(other.m_cont.comp()))
1470 insert(other.cbegin(), other.cend());
1503 Compare
const& comp)
1504 : m_config(clock, comp), m_cont(comp)
1521 Allocator
const& alloc)
1522 : m_config(clock, alloc)
1539 Compare
const& comp,
1540 Allocator
const& alloc)
1541 : m_config(clock, comp, alloc), m_cont(comp)
1575 this->m_config = other.m_config;
1576 insert(other.begin(), other.end());
1594 this->m_config = std::move(other.m_config);
1595 insert(other.begin(), other.end());
1627template <
class K,
bool maybe_multi,
bool maybe_map,
class>
1632 auto const iter(m_cont.find(k,
std::cref(m_config.key_compare())));
1633 if (iter == m_cont.end())
1635 return iter->value.second;
1646template <
class K,
bool maybe_multi,
bool maybe_map,
class>
1651 auto const iter(m_cont.find(k,
std::cref(m_config.key_compare())));
1652 if (iter == m_cont.end())
1654 return iter->value.second;
1665template <
bool maybe_multi,
bool maybe_map,
class>
1670 typename cont_type::insert_commit_data d;
1672 m_cont.insert_check(key,
std::cref(m_config.key_compare()), d));
1676 std::piecewise_construct,
1679 m_cont.insert_commit(*p, d);
1680 chronological.list.push_back(*p);
1681 return p->
value.second;
1683 return result.first->value.second;
1694template <
bool maybe_multi,
bool maybe_map,
class>
1699 typename cont_type::insert_commit_data d;
1701 m_cont.insert_check(key,
std::cref(m_config.key_compare()), d));
1705 std::piecewise_construct,
1708 m_cont.insert_commit(*p, d);
1709 chronological.list.push_back(*p);
1710 return p->
value.second;
1712 return result.first->value.second;
1729 for (
auto iter(chronological.list.begin());
1730 iter != chronological.list.end();)
1731 delete_element(&*iter++);
1732 chronological.list.clear();
1745template <
bool maybe_multi>
1751 typename cont_type::insert_commit_data d;
1752 auto const result(m_cont.insert_check(
1753 extract(value),
std::cref(m_config.key_compare()), d));
1756 element*
const p(new_element(value));
1757 auto const iter(m_cont.insert_commit(*p, d));
1758 chronological.list.push_back(*p);
1773template <
bool maybe_multi>
1776 insert(value_type
const& value) ->
1780 m_cont.upper_bound(extract(value),
std::cref(m_config.key_compare())));
1781 element*
const p(new_element(value));
1782 chronological.list.push_back(*p);
1783 auto const iter(m_cont.insert_before(before, *p));
1784 return iterator(iter);
1796template <
bool maybe_multi,
bool maybe_map>
1801 enable_if<!maybe_multi && !maybe_map, std::pair<iterator, bool>>::type
1803 typename cont_type::insert_commit_data d;
1804 auto const result(m_cont.insert_check(
1805 extract(value),
std::cref(m_config.key_compare()), d));
1808 element*
const p(new_element(std::move(value)));
1809 auto const iter(m_cont.insert_commit(*p, d));
1810 chronological.list.push_back(*p);
1825template <
bool maybe_multi,
bool maybe_map>
1828 insert(value_type&& value) ->
1832 m_cont.upper_bound(extract(value),
std::cref(m_config.key_compare())));
1833 element*
const p(new_element(std::move(value)));
1834 chronological.list.push_back(*p);
1835 auto const iter(m_cont.insert_before(before, *p));
1836 return iterator(iter);
1850template <
bool maybe_multi>
1856 typename cont_type::insert_commit_data d;
1857 auto const result(m_cont.insert_check(
1858 hint.iterator(), extract(value),
std::cref(m_config.key_compare()), d));
1861 element*
const p(new_element(value));
1862 auto const iter(m_cont.insert_commit(*p, d));
1863 chronological.list.push_back(*p);
1878template <
bool maybe_multi>
1884 typename cont_type::insert_commit_data d;
1885 auto const result(m_cont.insert_check(
1886 hint.iterator(), extract(value),
std::cref(m_config.key_compare()), d));
1889 element*
const p(new_element(std::move(value)));
1890 auto const iter(m_cont.insert_commit(*p, d));
1891 chronological.list.push_back(*p);
1906template <
bool maybe_multi,
class... Args>
1914 element*
const p(new_element(std::forward<Args>(args)...));
1915 typename cont_type::insert_commit_data d;
1916 auto const result(m_cont.insert_check(
1920 auto const iter(m_cont.insert_commit(*p, d));
1921 chronological.list.push_back(*p);
1937template <
bool maybe_multi,
class... Args>
1943 element*
const p(new_element(std::forward<Args>(args)...));
1944 auto const before(m_cont.upper_bound(
1945 extract(p->value),
std::cref(m_config.key_compare())));
1946 chronological.list.push_back(*p);
1947 auto const iter(m_cont.insert_before(before, *p));
1948 return iterator(iter);
1960template <
bool maybe_multi,
class... Args>
1968 element*
const p(new_element(std::forward<Args>(args)...));
1969 typename cont_type::insert_commit_data d;
1970 auto const result(m_cont.insert_check(
1977 auto const iter(m_cont.insert_commit(*p, d));
1978 chronological.list.push_back(*p);
1993template <
bool is_const,
class Iterator,
class>
1998 unlink_and_delete_element(&*((pos++).
iterator()));
2011template <
bool is_const,
class Iterator,
class>
2018 for (; first != last;)
2019 unlink_and_delete_element(&*((first++).
iterator()));
2038 auto iter(m_cont.find(k,
std::cref(m_config.key_compare())));
2039 if (iter == m_cont.end())
2045 bool const done(m_config(*p, extract(iter->value)));
2046 unlink_and_delete_element(p);
2067 std::swap(chronological, other.chronological);
2086 auto const now(clock().now());
2088 auto const range(equal_range(k));
2089 for (
auto iter : range)
2111 class OtherDuration,
2112 class OtherAllocator>
2122 OtherAllocator>
const& other)
const
2132 if (size() != other.size())
2141 value_type const& lhs,
typename Other::value_type
const& rhs) {
2142 return eq(extract(lhs), other.extract(rhs));
2156template <
bool is_const,
class Iterator,
class>
2165 chronological.list.erase(chronological.list.iterator_to(e));
2166 chronological.list.push_back(e);
2177template <
bool maybe_propagate>
2182 std::swap(m_config.key_compare(), other.m_config.key_compare());
2183 std::swap(m_config.alloc(), other.m_config.alloc());
2184 std::swap(m_config.clock, other.m_config.clock);
2195template <
bool maybe_propagate>
2200 std::swap(m_config.key_compare(), other.m_config.key_compare());
2201 std::swap(m_config.clock, other.m_config.clock);
2255 Allocator>& rhs)
noexcept
2284 auto const expired(c.clock().now() - age);
2285 for (
auto iter(c.chronological.cbegin());
2286 iter != c.chronological.cend() && iter.when() <= expired;)
2288 iter = c.erase(iter);
Abstract interface to a clock.
typename Clock::time_point time_point
typename Clock::duration duration
Iterator const & iterator() const
bool operator()(element const &e, Key const &k) const
Compare const & compare() const
bool operator()(element const &x, element const &y) const
KeyValueCompare(Compare const &compare)
KeyValueCompare()=default
bool operator()(Key const &k, element const &e) const
const_iterator iterator_to(value_type const &value) const
const_reverse_iterator rbegin() const
const_reverse_iterator crbegin() const
const_iterator cbegin() const
const_reverse_iterator crend() const
beast::detail::aged_container_iterator<!IsMap, typename list_type::iterator > iterator
chronological_t(chronological_t const &)=delete
reverse_iterator rbegin()
beast::detail::aged_container_iterator< !IsMap, typename list_type::reverse_iterator > reverse_iterator
const_iterator end() const
beast::detail::aged_container_iterator< true, typename list_type::reverse_iterator > const_reverse_iterator
const_reverse_iterator rend() const
const_iterator cend() const
beast::detail::aged_container_iterator< true, typename list_type::iterator > const_iterator
iterator iterator_to(value_type &value)
chronological_t(chronological_t &&)=delete
const_iterator begin() const
KeyValueCompare & key_compare()
config_t(config_t const &other, Allocator const &alloc)
ElementAllocator & alloc()
config_t(clock_type &clock_, Allocator const &alloc_)
KeyValueCompare const & key_compare() const
Compare const & compare() const
config_t & operator=(config_t &&other)
config_t(clock_type &clock_)
ElementAllocator const & alloc() const
config_t(config_t const &other)
std::reference_wrapper< clock_type > clock
config_t(clock_type &clock_, Compare const &comp, Allocator const &alloc_)
config_t & operator=(config_t const &other)
config_t(config_t &&other, Allocator const &alloc)
config_t(clock_type &clock_, Compare const &comp)
config_t(config_t &&other)
pair_value_compare(pair_value_compare const &other)
friend aged_ordered_container
value_type second_argument
bool operator()(value_type const &lhs, value_type const &rhs) const
pair_value_compare(Compare const &compare)
value_type first_argument
Associative container where each element is also indexed by time.
std::conditional< IsMap, T, void * >::type & operator[](Key const &key)
aged_ordered_container(aged_ordered_container &&other, Allocator const &alloc)
size_type touch(K const &k)
std::enable_if< maybe_multi, iterator >::type emplace_hint(const_iterator, Args &&... args)
typename std::allocator_traits< Allocator >::const_pointer const_pointer
aged_ordered_container(aged_ordered_container &&other)
value_compare value_comp() const
clock_type const & clock() const
auto insert(const_iterator hint, value_type const &value) -> typename std::enable_if<!maybe_multi, iterator >::type
aged_ordered_container(clock_type &clock)
std::conditional< IsMap, T, void * >::type & at(K const &k)
typename std::allocator_traits< Allocator >::pointer pointer
aged_ordered_container & operator=(std::initializer_list< value_type > init)
auto insert(value_type const &value) -> typename std::enable_if< maybe_multi, iterator >::type
const_iterator find(K const &k) const
reverse_iterator rbegin()
typename std::conditional< IsMap, pair_value_compare, Compare >::type value_compare
const_iterator cend() const
void swap(aged_ordered_container &other) noexcept
beast::detail::aged_container_iterator< false, Iterator > erase(beast::detail::aged_container_iterator< is_const, Iterator > pos)
const_reverse_iterator rbegin() const
beast::detail::aged_container_iterator< true, typename cont_type::reverse_iterator > const_reverse_iterator
aged_ordered_container(clock_type &clock, Compare const &comp)
~aged_ordered_container()
aged_ordered_container(aged_ordered_container const &other, Allocator const &alloc)
aged_ordered_container(std::initializer_list< value_type > init, clock_type &clock, Compare const &comp, Allocator const &alloc)
aged_ordered_container(std::initializer_list< value_type > init, clock_type &clock, Allocator const &alloc)
bool operator<=(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
aged_ordered_container(std::initializer_list< value_type > init, clock_type &clock)
aged_ordered_container & operator=(aged_ordered_container const &other)
aged_ordered_container(InputIt first, InputIt last, clock_type &clock, Allocator const &alloc)
bool operator>(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
auto insert(value_type &&value) -> typename std::enable_if< !maybe_multi &&!maybe_map, std::pair< iterator, bool > >::type
void insert(InputIt first, InputIt last)
const_reverse_iterator crend() const
std::pair< iterator, iterator > equal_range(K const &k)
bool operator==(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
aged_ordered_container(clock_type &clock, Compare const &comp, Allocator const &alloc)
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)
void insert(std::initializer_list< value_type > init)
aged_ordered_container(aged_ordered_container const &other)
value_type const & const_reference
void unlink_and_delete_element(element const *p)
aged_ordered_container(std::initializer_list< value_type > init, clock_type &clock, Compare const &comp)
const_iterator end() const
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)
const_iterator cbegin() const
const_iterator lower_bound(K const &k) const
typename std::conditional< IsMulti, typename boost::intrusive::make_multiset< element, boost::intrusive::constant_time_size< true >, boost::intrusive::compare< KeyValueCompare > >::type, typename boost::intrusive::make_set< element, boost::intrusive::constant_time_size< true >, boost::intrusive::compare< KeyValueCompare > >::type >::type cont_type
const_iterator upper_bound(K const &k) const
bool operator!=(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
const_iterator iterator_to(value_type const &value) const
std::enable_if< maybe_propagate >::type swap_data(aged_ordered_container &other) noexcept
allocator_type get_allocator() const
typename std::allocator_traits< Allocator >::template rebind_alloc< element > ElementAllocator
aged_ordered_container()=delete
auto insert(value_type &&value) -> typename std::enable_if< maybe_multi &&!maybe_map, iterator >::type
auto insert(value_type const &value) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
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)
std::enable_if< maybe_multi, iterator >::type insert(const_iterator, value_type const &value)
auto emplace(Args &&... args) -> typename std::enable_if< maybe_multi, iterator >::type
bool operator<(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
key_compare key_comp() const
iterator lower_bound(K const &k)
typename clock_type::duration duration
auto insert(const_iterator hint, value_type &&value) -> typename std::enable_if<!maybe_multi, iterator >::type
element * new_element(Args &&... args)
void touch(beast::detail::aged_container_iterator< is_const, Iterator > pos, typename clock_type::time_point const &now)
beast::detail::aged_container_iterator<!IsMap, typename cont_type::iterator > iterator
auto erase(K const &k) -> size_type
beast::detail::aged_container_iterator< true, typename cont_type::iterator > const_iterator
void touch(beast::detail::aged_container_iterator< is_const, Iterator > pos)
class beast::detail::aged_ordered_container::chronological_t chronological
size_type size() const noexcept
size_type count(K const &k) const
aged_ordered_container(clock_type &clock, Allocator const &alloc)
void delete_element(element const *p)
aged_ordered_container(InputIt first, InputIt last, clock_type &clock, Compare const &comp)
size_type max_size() const noexcept
const_iterator begin() const
aged_ordered_container(InputIt first, InputIt last, clock_type &clock, Compare const &comp, Allocator const &alloc)
aged_ordered_container & operator=(aged_ordered_container &&other)
std::enable_if< maybe_multi, iterator >::type insert(const_iterator, value_type &&value)
bool operator>=(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
abstract_clock< Clock > clock_type
typename boost::intrusive::make_list< element, boost::intrusive::constant_time_size< false > >::type list_type
iterator upper_bound(K const &k)
const_reverse_iterator crbegin() const
auto emplace_hint(const_iterator hint, 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
aged_ordered_container(InputIt first, InputIt last, clock_type &clock)
iterator find(K const &k)
typename std::conditional< IsMap, std::pair< Key const, T >, Key >::type value_type
auto emplace(Args &&... args) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
std::conditional< IsMap, T, void * >::type & operator[](Key &&key)
beast::detail::aged_container_iterator<!IsMap, typename cont_type::reverse_iterator > reverse_iterator
const_reverse_iterator rend() const
static Key const & extract(value_type const &value)
bool empty() const noexcept
std::pair< const_iterator, const_iterator > equal_range(K const &k) const
iterator iterator_to(value_type &value)
typename clock_type::time_point time_point
ElementAllocator & member() noexcept
T forward_as_tuple(T... args)
T lexicographical_compare(T... args)
int compare(SemanticVersion const &lhs, SemanticVersion const &rhs)
Compare two SemanticVersions against each other.
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
typename aged_ordered_container::time_point time_point
typename aged_ordered_container::value_type value_type
element(time_point const &when_, value_type const &value_)
element(time_point const &when_, value_type &&value_)
element(time_point const &when_, Args &&... args)
is_boost_reverse_iterator()=default
is_boost_reverse_iterator()=default
is_aged_container()=default