mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-23 23:20:33 +00:00
Merge branch 'develop' into ximinez/acquireAsyncDispatch
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <lz4.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -12,8 +13,8 @@ template <int Window, typename Clock>
|
||||
class DecayingSample
|
||||
{
|
||||
public:
|
||||
using value_type = typename Clock::duration::rep;
|
||||
using time_point = typename Clock::time_point;
|
||||
using value_type = Clock::duration::rep;
|
||||
using time_point = Clock::time_point;
|
||||
|
||||
DecayingSample() = delete;
|
||||
|
||||
@@ -93,7 +94,7 @@ template <int HalfLife, class Clock>
|
||||
class DecayWindow
|
||||
{
|
||||
public:
|
||||
using time_point = typename Clock::time_point;
|
||||
using time_point = Clock::time_point;
|
||||
|
||||
explicit DecayWindow(time_point now) : when_(now)
|
||||
{
|
||||
|
||||
@@ -1,248 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/contract.h>
|
||||
|
||||
#include <boost/outcome.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/** Expected is an approximation of std::expected (hoped for in C++23)
|
||||
|
||||
See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
|
||||
|
||||
The implementation is entirely based on boost::outcome_v2::result.
|
||||
*/
|
||||
|
||||
// Exception thrown by an invalid access to Expected.
|
||||
struct BadExpectedAccess : public std::runtime_error
|
||||
{
|
||||
BadExpectedAccess() : runtime_error("bad expected access")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Custom policy for Expected. Always throw on an invalid access.
|
||||
struct ThrowPolicy : public boost::outcome_v2::policy::base
|
||||
{
|
||||
template <class Impl>
|
||||
static constexpr void
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
wide_value_check(Impl&& self)
|
||||
{
|
||||
if (!base::_has_value(std::forward<Impl>(self)))
|
||||
Throw<BadExpectedAccess>();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
static constexpr void
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
wide_error_check(Impl&& self)
|
||||
{
|
||||
if (!base::_has_error(std::forward<Impl>(self)))
|
||||
Throw<BadExpectedAccess>();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
static constexpr void
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
wide_exception_check(Impl&& self)
|
||||
{
|
||||
if (!base::_has_exception(std::forward<Impl>(self)))
|
||||
Throw<BadExpectedAccess>();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Definition of Unexpected, which is used to construct the unexpected
|
||||
// return type of an Expected.
|
||||
template <class E>
|
||||
class Unexpected
|
||||
{
|
||||
public:
|
||||
static_assert(!std::is_same_v<E, void>, "E must not be void");
|
||||
|
||||
Unexpected() = delete;
|
||||
|
||||
constexpr explicit Unexpected(E const& e) : val_(e)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr explicit Unexpected(E&& e) : val_(std::move(e))
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E const&
|
||||
value() const&
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
constexpr E&
|
||||
value() &
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
constexpr E&&
|
||||
value() &&
|
||||
{
|
||||
return std::move(val_);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E const&&
|
||||
value() const&&
|
||||
{
|
||||
return std::move(val_);
|
||||
}
|
||||
|
||||
private:
|
||||
E val_;
|
||||
};
|
||||
|
||||
// Unexpected deduction guide that converts array to const*.
|
||||
template <typename E, std::size_t N>
|
||||
Unexpected(E (&)[N]) -> Unexpected<E const*>;
|
||||
|
||||
// Definition of Expected. All of the machinery comes from boost::result.
|
||||
template <class T, class E>
|
||||
class [[nodiscard]] Expected : private boost::outcome_v2::result<T, E, detail::ThrowPolicy>
|
||||
{
|
||||
using Base = boost::outcome_v2::result<T, E, detail::ThrowPolicy>;
|
||||
|
||||
public:
|
||||
template <typename U>
|
||||
requires std::convertible_to<U, T>
|
||||
constexpr Expected(U&& r) : Base(boost::outcome_v2::in_place_type_t<T>{}, std::forward<U>(r))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
requires std::convertible_to<U, E> && (!std::is_reference_v<U>)
|
||||
constexpr Expected(Unexpected<U> e)
|
||||
: Base(boost::outcome_v2::in_place_type_t<E>{}, std::move(e.value()))
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
has_value() const
|
||||
{
|
||||
return Base::has_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T const&
|
||||
value() const
|
||||
{
|
||||
return Base::value();
|
||||
}
|
||||
|
||||
constexpr T&
|
||||
value()
|
||||
{
|
||||
return Base::value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E const&
|
||||
error() const&
|
||||
{
|
||||
return Base::error();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E&
|
||||
error() &
|
||||
{
|
||||
return Base::error();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E&&
|
||||
error() &&
|
||||
{
|
||||
return std::move(Base::error());
|
||||
}
|
||||
|
||||
constexpr explicit
|
||||
operator bool() const
|
||||
{
|
||||
return has_value();
|
||||
}
|
||||
|
||||
// Add operator* and operator-> so the Expected API looks a bit more like
|
||||
// what std::expected is likely to look like. See:
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
|
||||
[[nodiscard]] constexpr T&
|
||||
operator*()
|
||||
{
|
||||
return this->value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T const&
|
||||
operator*() const
|
||||
{
|
||||
return this->value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T*
|
||||
operator->()
|
||||
{
|
||||
return &this->value();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T const*
|
||||
operator->() const
|
||||
{
|
||||
return &this->value();
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization of Expected<void, E>. Allows returning either success
|
||||
// (without a value) or the reason for the failure.
|
||||
template <class E>
|
||||
class [[nodiscard]]
|
||||
Expected<void, E> : private boost::outcome_v2::result<void, E, detail::ThrowPolicy>
|
||||
{
|
||||
using Base = boost::outcome_v2::result<void, E, detail::ThrowPolicy>;
|
||||
|
||||
public:
|
||||
// The default constructor makes a successful Expected<void, E>.
|
||||
// This aligns with std::expected behavior proposed in P0323R10.
|
||||
constexpr Expected() : Base(boost::outcome_v2::success())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
requires std::convertible_to<U, E> && (!std::is_reference_v<U>)
|
||||
constexpr Expected(Unexpected<U> e) : Base(E(std::move(e.value())))
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E const&
|
||||
error() const&
|
||||
{
|
||||
return Base::error();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E&
|
||||
error() &
|
||||
{
|
||||
return Base::error();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E&&
|
||||
error() &&
|
||||
{
|
||||
return std::move(Base::error());
|
||||
}
|
||||
|
||||
constexpr explicit
|
||||
operator bool() const
|
||||
{
|
||||
return Base::has_value();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -3,7 +3,9 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -641,6 +641,9 @@ template <class T>
|
||||
T*
|
||||
SharedWeakUnion<T>::unsafeGetRawPtr() const
|
||||
{
|
||||
// tp_ packs a raw pointer together with a strength bit; recovering the
|
||||
// pointer inherently requires an integer-to-pointer cast.
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
||||
return reinterpret_cast<T*>(tp_ & kPtrMask);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/UnorderedContainers.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
@@ -11,7 +10,9 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -206,8 +207,7 @@ private:
|
||||
#ifndef JLOG
|
||||
#define JLOG(x) \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
} \
|
||||
; \
|
||||
else \
|
||||
x
|
||||
#endif
|
||||
|
||||
@@ -2,12 +2,20 @@
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -38,17 +46,58 @@ isPowerOfTen(T value)
|
||||
return logTen(value).has_value();
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** Builds a table of the powers of 10
|
||||
*
|
||||
* This function is marked consteval, so it can only be run in
|
||||
* a constexpr context. This assures that it is and can only be run at
|
||||
* compile time. Doing it at runtime would be pretty wasteful and
|
||||
* inefficient.
|
||||
*/
|
||||
constexpr std::size_t kInt64Digits = 20;
|
||||
consteval std::array<std::uint64_t, kInt64Digits>
|
||||
buildPowersOfTen()
|
||||
{
|
||||
std::array<std::uint64_t, kInt64Digits> result{};
|
||||
|
||||
std::uint64_t power = 1;
|
||||
std::size_t exponent = 0;
|
||||
// end the loop early so it doesn't overflow;
|
||||
for (; exponent < result.size() - 1; ++exponent, power *= 10)
|
||||
{
|
||||
result[exponent] = power;
|
||||
if (power > std::numeric_limits<std::uint64_t>::max() / 10)
|
||||
throw std::logic_error("Power of 10 table is too big");
|
||||
}
|
||||
result[exponent] = power;
|
||||
if (power < std::numeric_limits<std::uint64_t>::max() / 10)
|
||||
throw std::logic_error("Power of 10 table is not big enough for the uint64_t type");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
constexpr std::array<std::uint64_t, detail::kInt64Digits> kPowerOfTen = detail::buildPowersOfTen();
|
||||
|
||||
static_assert(kPowerOfTen[0] == 1);
|
||||
static_assert(kPowerOfTen[1] == 10);
|
||||
static_assert(kPowerOfTen[10] == 10'000'000'000);
|
||||
static_assert(
|
||||
isPowerOfTen(kPowerOfTen.back()) && *logTen(kPowerOfTen.back()) == detail::kInt64Digits - 1);
|
||||
|
||||
/** MantissaRange defines a range for the mantissa of a normalized Number.
|
||||
*
|
||||
* The mantissa is in the range [min, max], where
|
||||
* * min is a power of 10, and
|
||||
* * max = min * 10 - 1.
|
||||
*
|
||||
* The mantissa_scale enum indicates whether the range is "small" or "large".
|
||||
* This intentionally restricts the number of MantissaRanges that can be
|
||||
* instantiated to two: one for each scale.
|
||||
* The MantissaScale enum indicates properties of the range: size, and some behavioral
|
||||
* options. This intentionally restricts the number of unique MantissaRanges that can
|
||||
* be instantiated: one for each scale.
|
||||
*
|
||||
* The "small" scale is based on the behavior of STAmount for IOUs. It has a min
|
||||
* The "Small" scale is based on the behavior of STAmount for IOUs. It has a min
|
||||
* value of 10^15, and a max value of 10^16-1. This was sufficient for
|
||||
* uses before Lending Protocol was implemented, mostly related to AMM.
|
||||
*
|
||||
@@ -59,46 +108,100 @@ isPowerOfTen(T value)
|
||||
* STNumber field type, and for internal calculations. That necessitated the
|
||||
* "large" scale.
|
||||
*
|
||||
* The "large" scale is intended to represent all values that can be represented
|
||||
* The "Large" scales are intended to represent all values that can be represented
|
||||
* by an STAmount - IOUs, XRP, and MPTs. It has a min value of 10^18, and a max
|
||||
* value of 10^19-1.
|
||||
* value of 10^19-1. "LargeLegacy" is like "Large", but preserves
|
||||
* a rounding error when a computation results in a mantissa of
|
||||
* Number::kMaxRep that needs to be rounded up, but rounds down
|
||||
* instead. It will maintain consistent behavior until the fixCleanup3_2_0
|
||||
* amendment is enabled.
|
||||
*
|
||||
* Note that if the mentioned amendments are eventually retired, this class
|
||||
* should be left in place, but the "small" scale option should be removed. This
|
||||
* should be left in place, but the "Small" scale option should be removed. This
|
||||
* will allow for future expansion beyond 64-bits if it is ever needed.
|
||||
*/
|
||||
struct MantissaRange
|
||||
struct MantissaRange final
|
||||
{
|
||||
using rep = std::uint64_t;
|
||||
enum class MantissaScale { Small, Large };
|
||||
|
||||
explicit constexpr MantissaRange(MantissaScale scale)
|
||||
: min(getMin(scale)), log(logTen(min).value_or(-1)), scale(scale)
|
||||
enum class MantissaScale {
|
||||
Small,
|
||||
// LargeLegacy can be removed when fixCleanup3_2_0 is retired
|
||||
LargeLegacy,
|
||||
Large,
|
||||
};
|
||||
|
||||
// This entire enum can be removed when fixCleanup3_2_0 is retired
|
||||
enum class CuspRoundingFix : bool {
|
||||
Disabled = false,
|
||||
Enabled = true,
|
||||
};
|
||||
|
||||
explicit constexpr MantissaRange(MantissaScale sc) : scale(sc)
|
||||
{
|
||||
}
|
||||
|
||||
rep min;
|
||||
rep max{(min * 10) - 1};
|
||||
int log;
|
||||
MantissaScale scale;
|
||||
MantissaScale const scale;
|
||||
int const log{getExponent(scale)};
|
||||
rep const min{getMin(scale, log)};
|
||||
rep const max{(min * 10) - 1};
|
||||
CuspRoundingFix const cuspRoundingFixEnabled{isCuspFixEnabled(scale)};
|
||||
|
||||
static MantissaRange const&
|
||||
getMantissaRange(MantissaScale scale);
|
||||
|
||||
static std::set<MantissaScale> const&
|
||||
getAllScales();
|
||||
|
||||
private:
|
||||
static constexpr rep
|
||||
getMin(MantissaScale scale)
|
||||
static constexpr int
|
||||
getExponent(MantissaScale scale)
|
||||
{
|
||||
switch (scale)
|
||||
{
|
||||
case MantissaScale::Small:
|
||||
return 1'000'000'000'000'000ULL;
|
||||
return 15;
|
||||
case MantissaScale::LargeLegacy:
|
||||
case MantissaScale::Large:
|
||||
return 1'000'000'000'000'000'000ULL;
|
||||
return 18;
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
// Since this can never be called outside a non-constexpr
|
||||
// context, this throw assures that the build fails if an
|
||||
// If called in a constexpr context, this throw assures that the build fails if an
|
||||
// invalid scale is used.
|
||||
throw std::runtime_error("Unknown mantissa scale");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
// Keep this function for future use with different ways to compute
|
||||
// the ranges.
|
||||
static constexpr rep
|
||||
getMin(MantissaScale scale, int exponent)
|
||||
{
|
||||
if (exponent < 0 || exponent >= kPowerOfTen.size())
|
||||
throw std::runtime_error("Invalid exponent"); // LCOV_EXCL_LINE
|
||||
return kPowerOfTen[exponent];
|
||||
}
|
||||
|
||||
static constexpr CuspRoundingFix
|
||||
isCuspFixEnabled(MantissaScale scale)
|
||||
{
|
||||
switch (scale)
|
||||
{
|
||||
case MantissaScale::Small:
|
||||
case MantissaScale::LargeLegacy:
|
||||
return CuspRoundingFix::Disabled;
|
||||
case MantissaScale::Large:
|
||||
return CuspRoundingFix::Enabled;
|
||||
default:
|
||||
// If called in a constexpr context, this throw assures that the build fails if an
|
||||
// invalid scale is used.
|
||||
throw std::runtime_error("Unknown mantissa scale"); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
static std::unordered_map<MantissaScale, MantissaRange> const&
|
||||
getRanges();
|
||||
};
|
||||
|
||||
// Like std::integral, but only 64-bit integral types.
|
||||
@@ -203,7 +306,7 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
|
||||
* amendments are enabled to determine which result to expect.
|
||||
*
|
||||
*/
|
||||
class Number
|
||||
class Number final
|
||||
{
|
||||
using rep = std::int64_t;
|
||||
using internalrep = MantissaRange::rep;
|
||||
@@ -309,33 +412,40 @@ public:
|
||||
}
|
||||
|
||||
friend constexpr bool
|
||||
operator<(Number const& x, Number const& y) noexcept
|
||||
operator<(Number const& l, Number const& r) noexcept
|
||||
{
|
||||
bool const lneg = l.negative_;
|
||||
bool const rneg = r.negative_;
|
||||
|
||||
// If the two amounts have different signs (zero is treated as positive)
|
||||
// then the comparison is true iff the left is negative.
|
||||
bool const lneg = x.negative_;
|
||||
bool const rneg = y.negative_;
|
||||
|
||||
if (lneg != rneg)
|
||||
return lneg;
|
||||
|
||||
// Both have same sign and the left is zero: the right must be
|
||||
// greater than 0.
|
||||
if (x.mantissa_ == 0)
|
||||
return y.mantissa_ > 0;
|
||||
// Both have same sign and the left is zero: both must be non-negative.
|
||||
// If the right is greater than 0, then it is larger, so the comparison is true.
|
||||
if (l.mantissa_ == 0)
|
||||
return r.mantissa_ > 0;
|
||||
|
||||
// Both have same sign, the right is zero and the left is non-zero.
|
||||
if (y.mantissa_ == 0)
|
||||
// Both have same sign, the right is zero and the left is non-zero, so the left must be
|
||||
// positive, and thus is larger, so the comparison is false.
|
||||
if (r.mantissa_ == 0)
|
||||
return false;
|
||||
|
||||
// Both have the same sign, compare by exponents:
|
||||
if (x.exponent_ > y.exponent_)
|
||||
if (l.exponent_ > r.exponent_)
|
||||
return lneg;
|
||||
if (x.exponent_ < y.exponent_)
|
||||
if (l.exponent_ < r.exponent_)
|
||||
return !lneg;
|
||||
|
||||
// If equal exponents, compare mantissas
|
||||
return x.mantissa_ < y.mantissa_;
|
||||
// If equal signs and exponents, compare mantissas.
|
||||
if (lneg)
|
||||
{
|
||||
// If negative, the operator is reversed.
|
||||
return l.mantissa_ > r.mantissa_;
|
||||
}
|
||||
|
||||
return l.mantissa_ < r.mantissa_;
|
||||
}
|
||||
|
||||
/** Return the sign of the amount */
|
||||
@@ -424,49 +534,28 @@ public:
|
||||
return kRange.get().log;
|
||||
}
|
||||
|
||||
/// oneSmall is needed because the ranges are private
|
||||
static constexpr Number
|
||||
oneSmall();
|
||||
/// oneLarge is needed because the ranges are private
|
||||
static constexpr Number
|
||||
oneLarge();
|
||||
|
||||
// And one is needed because it needs to choose between oneSmall and
|
||||
// oneLarge based on the current range
|
||||
static Number
|
||||
one();
|
||||
|
||||
template <Integral64 T>
|
||||
template <
|
||||
auto MinMantissa,
|
||||
auto MaxMantissa,
|
||||
Integral64 T = std::decay_t<decltype(MinMantissa)>>
|
||||
[[nodiscard]]
|
||||
std::pair<T, int>
|
||||
normalizeToRange(T minMantissa, T maxMantissa) const;
|
||||
normalizeToRange() const;
|
||||
|
||||
private:
|
||||
static thread_local RoundingMode mode;
|
||||
// The available ranges for mantissa
|
||||
|
||||
static constexpr MantissaRange kSmallRange{MantissaRange::MantissaScale::Small};
|
||||
static_assert(isPowerOfTen(kSmallRange.min));
|
||||
static_assert(kSmallRange.min == 1'000'000'000'000'000LL);
|
||||
static_assert(kSmallRange.max == 9'999'999'999'999'999LL);
|
||||
static_assert(kSmallRange.log == 15);
|
||||
static_assert(kSmallRange.min < kMaxRep);
|
||||
static_assert(kSmallRange.max < kMaxRep);
|
||||
static constexpr MantissaRange kLargeRange{MantissaRange::MantissaScale::Large};
|
||||
static_assert(isPowerOfTen(kLargeRange.min));
|
||||
static_assert(kLargeRange.min == 1'000'000'000'000'000'000ULL);
|
||||
static_assert(kLargeRange.max == internalrep(9'999'999'999'999'999'999ULL));
|
||||
static_assert(kLargeRange.log == 18);
|
||||
static_assert(kLargeRange.min < kMaxRep);
|
||||
static_assert(kLargeRange.max > kMaxRep);
|
||||
|
||||
// The range for the mantissa when normalized.
|
||||
// Use reference_wrapper to avoid making copies, and prevent accidentally
|
||||
// changing the values inside the range.
|
||||
static thread_local std::reference_wrapper<MantissaRange const> kRange;
|
||||
|
||||
void
|
||||
normalize();
|
||||
normalize(MantissaRange const& range);
|
||||
|
||||
/** Normalize Number components to an arbitrary range.
|
||||
*
|
||||
@@ -481,7 +570,8 @@ private:
|
||||
T& mantissa,
|
||||
int& exponent,
|
||||
internalrep const& minMantissa,
|
||||
internalrep const& maxMantissa);
|
||||
internalrep const& maxMantissa,
|
||||
MantissaRange::CuspRoundingFix cuspRoundingFixEnabled);
|
||||
|
||||
template <class T>
|
||||
friend void
|
||||
@@ -490,7 +580,9 @@ private:
|
||||
T& mantissa,
|
||||
int& exponent,
|
||||
MantissaRange::rep const& minMantissa,
|
||||
MantissaRange::rep const& maxMantissa);
|
||||
MantissaRange::rep const& maxMantissa,
|
||||
MantissaRange::CuspRoundingFix cuspRoundingFixEnabled,
|
||||
bool dropped);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isnormal() const noexcept;
|
||||
@@ -526,7 +618,7 @@ static constexpr Number kNumZero{};
|
||||
inline Number::Number(bool negative, internalrep mantissa, int exponent, Normalized)
|
||||
: Number(negative, mantissa, exponent, Unchecked{})
|
||||
{
|
||||
normalize();
|
||||
normalize(kRange);
|
||||
}
|
||||
|
||||
inline Number::Number(internalrep mantissa, int exponent, Normalized)
|
||||
@@ -696,10 +788,21 @@ Number::isnormal() const noexcept
|
||||
kMinExponent <= exponent_ && exponent_ <= kMaxExponent);
|
||||
}
|
||||
|
||||
template <Integral64 T>
|
||||
template <auto MinMantissa, auto MaxMantissa, Integral64 T>
|
||||
std::pair<T, int>
|
||||
Number::normalizeToRange(T minMantissa, T maxMantissa) const
|
||||
Number::normalizeToRange() const
|
||||
{
|
||||
static_assert(std::is_same_v<T, std::uint64_t> || std::is_same_v<T, std::int64_t>);
|
||||
static_assert(std::is_same_v<T, std::decay_t<decltype(MinMantissa)>>);
|
||||
static_assert(std::is_same_v<T, std::decay_t<decltype(MaxMantissa)>>);
|
||||
auto constexpr kMIN = static_cast<T>(MinMantissa);
|
||||
auto constexpr kMAX = static_cast<T>(MaxMantissa);
|
||||
static_assert(kMIN > 0);
|
||||
static_assert(kMIN % 10 == 0);
|
||||
static_assert(isPowerOfTen(kMIN));
|
||||
static_assert(kMAX % 10 == 9);
|
||||
static_assert((kMAX + 1) / 10 == kMIN);
|
||||
|
||||
bool negative = negative_;
|
||||
internalrep mantissa = mantissa_;
|
||||
int exponent = exponent_;
|
||||
@@ -711,7 +814,10 @@ Number::normalizeToRange(T minMantissa, T maxMantissa) const
|
||||
"xrpl::Number::normalizeToRange",
|
||||
"Number is non-negative for unsigned range.");
|
||||
}
|
||||
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
|
||||
// Don't need to worry about the cuspRounding fix because rounding up will never take the
|
||||
// mantissa over maxMantissa with a ones digit value other than 0. 0 can safely be truncated.
|
||||
Number::normalize(
|
||||
negative, mantissa, exponent, kMIN, kMAX, MantissaRange::CuspRoundingFix::Disabled);
|
||||
|
||||
auto const sign = negative ? -1 : 1;
|
||||
return std::make_pair(static_cast<T>(sign * mantissa), exponent);
|
||||
@@ -763,6 +869,8 @@ to_string(MantissaRange::MantissaScale const& scale)
|
||||
{
|
||||
case MantissaRange::MantissaScale::Small:
|
||||
return "small";
|
||||
case MantissaRange::MantissaScale::LargeLegacy:
|
||||
return "largeLegacy";
|
||||
case MantissaRange::MantissaScale::Large:
|
||||
return "large";
|
||||
default:
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <boost/icl/closed_interval.hpp>
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class ResolverAsio : public Resolver
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/partitioned_unordered_map.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#if BOOST_OS_LINUX
|
||||
|
||||
@@ -211,15 +211,17 @@ operator<<(Stream& s, Slice const& v)
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
std::enable_if_t<std::is_same_v<T, char> || std::is_same_v<T, unsigned char>, Slice>
|
||||
Slice
|
||||
makeSlice(std::array<T, N> const& a)
|
||||
requires(std::is_same_v<T, char> || std::is_same_v<T, unsigned char>)
|
||||
{
|
||||
return Slice(a.data(), a.size());
|
||||
}
|
||||
|
||||
template <class T, class Alloc>
|
||||
std::enable_if_t<std::is_same_v<T, char> || std::is_same_v<T, unsigned char>, Slice>
|
||||
Slice
|
||||
makeSlice(std::vector<T, Alloc> const& v)
|
||||
requires(std::is_same_v<T, char> || std::is_same_v<T, unsigned char>)
|
||||
{
|
||||
return Slice(v.data(), v.size());
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -95,13 +97,7 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end)
|
||||
}
|
||||
|
||||
inline std::optional<Blob>
|
||||
strUnHex(std::string const& strSrc)
|
||||
{
|
||||
return strUnHex(strSrc.size(), strSrc.cbegin(), strSrc.cend());
|
||||
}
|
||||
|
||||
inline std::optional<Blob>
|
||||
strViewUnHex(std::string_view strSrc)
|
||||
strUnHex(std::string_view strSrc)
|
||||
{
|
||||
return strUnHex(strSrc.size(), strSrc.cbegin(), strSrc.cend());
|
||||
}
|
||||
|
||||
@@ -1,22 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/IntrusivePointer.h>
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/SharedWeakCachePointer.ipp>
|
||||
#include <xrpl/basics/SharedWeakCachePointer.h>
|
||||
#include <xrpl/basics/SharedWeakCachePointer.ipp> // IWYU pragma: keep
|
||||
#include <xrpl/basics/UnorderedContainers.h>
|
||||
#include <xrpl/basics/hardened_hash.h>
|
||||
#include <xrpl/beast/clock/abstract_clock.h>
|
||||
#include <xrpl/beast/insight/Insight.h>
|
||||
#include <xrpl/beast/insight/Collector.h>
|
||||
#include <xrpl/beast/insight/Gauge.h>
|
||||
#include <xrpl/beast/insight/Hook.h>
|
||||
#include <xrpl/beast/insight/NullCollector.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a
|
||||
// collision when the key already exists (defined in TaggedCache.ipp):
|
||||
// - ReplaceCached: always replace the cached value with `data`. `data` is
|
||||
// never written back and may be const.
|
||||
// - ReplaceClient: keep the cached value and write it back into `data` (the
|
||||
// client's pointer), which must therefore be writable.
|
||||
// - ReplaceDynamically: call the supplied callback to decide per call; `data`
|
||||
// is written back when the cached value is kept, so it must be writable.
|
||||
struct ReplaceCached;
|
||||
struct ReplaceClient;
|
||||
struct ReplaceDynamically;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/** Map/cache combination.
|
||||
This class implements a cache and a map. The cache keeps objects alive
|
||||
in the map. The map allows multiple code paths that reference objects
|
||||
@@ -96,6 +120,32 @@ public:
|
||||
bool
|
||||
del(key_type const& key, bool valid);
|
||||
|
||||
private:
|
||||
// Selects the `data` parameter type of canonicalizeImpl from the replace
|
||||
// policy: const for detail::ReplaceCached (never written back), otherwise
|
||||
// writable.
|
||||
template <typename Policy>
|
||||
using CanonicalizeClientPointerType = std::conditional_t<
|
||||
std::is_same_v<detail::ReplaceCached, Policy>,
|
||||
SharedPointerType const&,
|
||||
SharedPointerType&>;
|
||||
|
||||
/** Shared implementation of the canonicalize family.
|
||||
|
||||
`policy` selects how a collision is resolved when `key` already exists:
|
||||
detail::ReplaceCached, detail::ReplaceClient or
|
||||
detail::ReplaceDynamically. For ReplaceDynamically `replaceCallback` is
|
||||
invoked with the existing strong pointer and returns whether to replace
|
||||
the cached value with `data`; for the tag policies it is unused.
|
||||
*/
|
||||
template <class Policy, class Callback = std::nullptr_t>
|
||||
bool
|
||||
canonicalizeImpl(
|
||||
key_type const& key,
|
||||
CanonicalizeClientPointerType<Policy> data,
|
||||
Policy policy,
|
||||
Callback&& replaceCallback = nullptr);
|
||||
|
||||
public:
|
||||
/** Replace aliased objects with originals.
|
||||
|
||||
@@ -104,19 +154,52 @@ public:
|
||||
This routine eliminates the duplicate and performs a replacement
|
||||
on the callers shared pointer if needed.
|
||||
|
||||
`replaceCallback` is a callable taking the existing strong pointer and
|
||||
returning whether to replace the cached value with `data` (true) or to
|
||||
keep the cached value and write it back into `data` (false). Because the
|
||||
write-back case mutates `data`, `data` must be writable.
|
||||
|
||||
@param key The key corresponding to the object
|
||||
@param data A shared pointer to the data corresponding to the object.
|
||||
@param replace Function that decides if cache should be replaced
|
||||
@param replaceCallback A callable (existing strong pointer -> bool).
|
||||
|
||||
@return `true` If the key already existed.
|
||||
*/
|
||||
template <class R>
|
||||
@return `true` if an existing live entry was found and used; `false` if a new entry was
|
||||
inserted or an expired tracked entry was re-cached.
|
||||
**/
|
||||
template <class Callback>
|
||||
bool
|
||||
canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback);
|
||||
canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback);
|
||||
|
||||
/** Insert/update the canonical entry for `key`, always replacing the
|
||||
cached value with `data`.
|
||||
|
||||
If an entry already exists for `key`, the cached value is unconditionally
|
||||
replaced with `data`; otherwise `data` is inserted. `data` is never
|
||||
written back, so it may be const.
|
||||
|
||||
@param key The key corresponding to the object.
|
||||
@param data A shared pointer to the data corresponding to the object.
|
||||
|
||||
@return `true` if an existing live entry was found and used; `false` if a new entry was
|
||||
inserted or an expired tracked entry was re-cached.
|
||||
**/
|
||||
bool
|
||||
canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data);
|
||||
|
||||
/** Insert the canonical entry for `key`, keeping any existing cached value.
|
||||
|
||||
If an entry already exists for `key`, the cached value is kept and
|
||||
written back into `data` so the caller ends up with the canonical
|
||||
object; otherwise `data` is inserted. Because `data` may be overwritten
|
||||
it must be writable.
|
||||
|
||||
@param key The key corresponding to the object.
|
||||
@param data A shared pointer to the data corresponding to the object;
|
||||
updated to the canonical value when one already exists.
|
||||
|
||||
@return `true` if an existing live entry was found and used; `false` if a new entry was
|
||||
inserted or an expired tracked entry was re-cached.
|
||||
**/
|
||||
bool
|
||||
canonicalizeReplaceClient(key_type const& key, SharedPointerType& data);
|
||||
|
||||
@@ -129,11 +212,13 @@ public:
|
||||
*/
|
||||
template <class ReturnType = bool>
|
||||
auto
|
||||
insert(key_type const& key, T const& value) -> std::enable_if_t<!IsKeyCache, ReturnType>;
|
||||
insert(key_type const& key, T const& value) -> ReturnType
|
||||
requires(!IsKeyCache);
|
||||
|
||||
template <class ReturnType = bool>
|
||||
auto
|
||||
insert(key_type const& key) -> std::enable_if_t<IsKeyCache, ReturnType>;
|
||||
insert(key_type const& key) -> ReturnType
|
||||
requires IsKeyCache;
|
||||
|
||||
// VFALCO NOTE It looks like this returns a copy of the data in
|
||||
// the output parameter 'data'. This could be expensive.
|
||||
@@ -157,7 +242,7 @@ public:
|
||||
/** Fetch an item from the cache.
|
||||
If the digest was not found, Handler
|
||||
will be called with this signature:
|
||||
std::shared_ptr<SLE const>(void)
|
||||
SLE::const_pointer(void)
|
||||
*/
|
||||
template <class Handler>
|
||||
SharedPointerType
|
||||
@@ -181,14 +266,14 @@ private:
|
||||
beast::insight::Collector::ptr const& collector)
|
||||
: hook(collector->makeHook(handler))
|
||||
, size(collector->makeGauge(prefix, "size"))
|
||||
, hit_rate(collector->makeGauge(prefix, "hit_rate"))
|
||||
, hitRate(collector->makeGauge(prefix, "hit_rate"))
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
beast::insight::Hook hook;
|
||||
beast::insight::Gauge size;
|
||||
beast::insight::Gauge hit_rate;
|
||||
beast::insight::Gauge hitRate;
|
||||
|
||||
std::size_t hits{0};
|
||||
std::size_t misses{0};
|
||||
@@ -197,16 +282,16 @@ private:
|
||||
class KeyOnlyEntry
|
||||
{
|
||||
public:
|
||||
clock_type::time_point last_access;
|
||||
clock_type::time_point lastAccess;
|
||||
|
||||
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : last_access(lastAccess)
|
||||
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : lastAccess(lastAccess)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
touch(clock_type::time_point const& now)
|
||||
{
|
||||
last_access = now;
|
||||
lastAccess = now;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -214,10 +299,10 @@ private:
|
||||
{
|
||||
public:
|
||||
shared_weak_combo_pointer_type ptr;
|
||||
clock_type::time_point last_access;
|
||||
clock_type::time_point lastAccess;
|
||||
|
||||
ValueEntry(clock_type::time_point const& lastAccess, shared_pointer_type const& ptr)
|
||||
: ptr(ptr), last_access(lastAccess)
|
||||
: ptr(ptr), lastAccess(lastAccess)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -246,7 +331,7 @@ private:
|
||||
void
|
||||
touch(clock_type::time_point const& now)
|
||||
{
|
||||
last_access = now;
|
||||
lastAccess = now;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -262,7 +347,7 @@ private:
|
||||
sweepHelper(
|
||||
clock_type::time_point const& whenExpire,
|
||||
[[maybe_unused]] clock_type::time_point const& now,
|
||||
typename KeyValueCacheType::map_type& partition,
|
||||
KeyValueCacheType::map_type& partition,
|
||||
SweptPointersVector& stuffToSweep,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::scoped_lock<std::recursive_mutex> const&);
|
||||
@@ -271,7 +356,7 @@ private:
|
||||
sweepHelper(
|
||||
clock_type::time_point const& whenExpire,
|
||||
clock_type::time_point const& now,
|
||||
typename KeyOnlyCacheType::map_type& partition,
|
||||
KeyOnlyCacheType::map_type& partition,
|
||||
SweptPointersVector&,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::scoped_lock<std::recursive_mutex> const&);
|
||||
@@ -286,13 +371,13 @@ private:
|
||||
std::string name_;
|
||||
|
||||
// Desired number of cache entries (0 = ignore)
|
||||
int const target_size_;
|
||||
int const targetSize_;
|
||||
|
||||
// Desired maximum cache age
|
||||
clock_type::duration const target_age_;
|
||||
clock_type::duration const targetAge_;
|
||||
|
||||
// Number of items cached
|
||||
int cache_count_{0};
|
||||
int cacheCount_{0};
|
||||
cache_type cache_; // Hold strong reference to recent objects
|
||||
std::uint64_t hits_{0};
|
||||
std::uint64_t misses_{0};
|
||||
|
||||
@@ -1,10 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/IntrusivePointer.ipp>
|
||||
#include <xrpl/basics/Log.h> // IWYU pragma: keep
|
||||
#include <xrpl/basics/TaggedCache.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a
|
||||
// collision when the key already exists:
|
||||
// - ReplaceCached: always replace the cached value with `data`. `data` is
|
||||
// never written back and may be const.
|
||||
// - ReplaceClient: keep the cached value and write it back into `data` (the
|
||||
// client's pointer), which must therefore be writable.
|
||||
// - ReplaceDynamically: call the supplied callback to decide per call; `data`
|
||||
// is written back when the cached value is kept, so it must be writable.
|
||||
struct ReplaceCached
|
||||
{
|
||||
};
|
||||
|
||||
struct ReplaceClient
|
||||
{
|
||||
};
|
||||
|
||||
struct ReplaceDynamically
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <
|
||||
class Key,
|
||||
class T,
|
||||
@@ -32,10 +57,13 @@ inline TaggedCache<
|
||||
beast::insight::Collector::ptr const& collector)
|
||||
: journal_(journal)
|
||||
, clock_(clock)
|
||||
, stats_(name, std::bind(&TaggedCache::collectMetrics, this), collector)
|
||||
, stats_(
|
||||
name,
|
||||
[this] { collectMetrics(); },
|
||||
collector)
|
||||
, name_(name)
|
||||
, target_size_(size)
|
||||
, target_age_(expiration)
|
||||
, targetSize_(size)
|
||||
, targetAge_(expiration)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -86,7 +114,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
getCacheSize() const
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
return cache_count_;
|
||||
return cacheCount_;
|
||||
}
|
||||
|
||||
template <
|
||||
@@ -139,7 +167,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
cache_.clear();
|
||||
cache_count_ = 0;
|
||||
cacheCount_ = 0;
|
||||
}
|
||||
|
||||
template <
|
||||
@@ -157,7 +185,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
cache_.clear();
|
||||
cache_count_ = 0;
|
||||
cacheCount_ = 0;
|
||||
hits_ = 0;
|
||||
misses_ = 0;
|
||||
}
|
||||
@@ -213,21 +241,21 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
if (target_size_ == 0 || (static_cast<int>(cache_.size()) <= target_size_))
|
||||
if (targetSize_ == 0 || (static_cast<int>(cache_.size()) <= targetSize_))
|
||||
{
|
||||
whenExpire = now - target_age_;
|
||||
whenExpire = now - targetAge_;
|
||||
}
|
||||
else
|
||||
{
|
||||
whenExpire = now - (target_age_ * target_size_ / cache_.size());
|
||||
whenExpire = now - (targetAge_ * targetSize_ / cache_.size());
|
||||
|
||||
clock_type::duration const minimumAge(std::chrono::seconds(1));
|
||||
if (whenExpire > (now - minimumAge))
|
||||
whenExpire = now - minimumAge;
|
||||
|
||||
JLOG(journal_.trace())
|
||||
<< name_ << " is growing fast " << cache_.size() << " of " << target_size_
|
||||
<< " aging at " << (now - whenExpire).count() << " of " << target_age_.count();
|
||||
<< name_ << " is growing fast " << cache_.size() << " of " << targetSize_
|
||||
<< " aging at " << (now - whenExpire).count() << " of " << targetAge_.count();
|
||||
}
|
||||
|
||||
std::vector<std::thread> workers;
|
||||
@@ -242,7 +270,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
for (std::thread& worker : workers)
|
||||
worker.join();
|
||||
|
||||
cache_count_ -= allRemovals;
|
||||
cacheCount_ -= allRemovals;
|
||||
}
|
||||
// At this point allStuffToSweep will go out of scope outside the lock
|
||||
// and decrement the reference count on each strong pointer.
|
||||
@@ -280,7 +308,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
--cache_count_;
|
||||
--cacheCount_;
|
||||
entry.ptr.convertToWeak();
|
||||
ret = true;
|
||||
}
|
||||
@@ -300,13 +328,29 @@ template <
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
template <class R>
|
||||
template <class Policy, class Callback>
|
||||
inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
|
||||
canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback)
|
||||
canonicalizeImpl(
|
||||
key_type const& key,
|
||||
CanonicalizeClientPointerType<Policy> data,
|
||||
[[maybe_unused]] Policy policy,
|
||||
[[maybe_unused]] Callback&& replaceCallback)
|
||||
{
|
||||
// Return canonical value, store if needed, refresh in cache
|
||||
// Return values: true=we had the data already
|
||||
|
||||
// `Policy` is one of:
|
||||
// - detail::ReplaceCached: always replace the cached value with `data`;
|
||||
// `data` is never written back and may be const.
|
||||
// - detail::ReplaceClient: keep the cached value and write it back into
|
||||
// `data` (the client's pointer), which must therefore be writable.
|
||||
// - detail::ReplaceDynamically: call `replaceCallback` to decide at run
|
||||
// time; `data` must be writable.
|
||||
// For the latter two the write-back below requires a mutable `data`, so
|
||||
// passing a const argument is a compile error.
|
||||
constexpr bool replaceCached = std::is_same_v<Policy, detail::ReplaceCached>;
|
||||
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
auto cit = cache_.find(key);
|
||||
@@ -317,20 +361,21 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(key),
|
||||
std::forward_as_tuple(clock_.now(), data));
|
||||
++cache_count_;
|
||||
++cacheCount_;
|
||||
return false;
|
||||
}
|
||||
|
||||
Entry& entry = cit->second;
|
||||
entry.touch(clock_.now());
|
||||
|
||||
auto shouldReplace = [&] {
|
||||
if constexpr (std::is_invocable_r_v<bool, R>)
|
||||
auto shouldReplaceCached = [&] {
|
||||
if constexpr (replaceCached)
|
||||
{
|
||||
// The reason for this extra complexity is for intrusive
|
||||
// strong/weak combo getting a strong is relatively expensive
|
||||
// and not needed for many cases.
|
||||
return replaceCallback();
|
||||
return true;
|
||||
}
|
||||
else if constexpr (std::is_same_v<Policy, detail::ReplaceClient>)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -340,11 +385,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
if (shouldReplace())
|
||||
if (shouldReplaceCached())
|
||||
{
|
||||
entry.ptr = data;
|
||||
}
|
||||
else
|
||||
else if constexpr (!replaceCached)
|
||||
{
|
||||
data = entry.ptr.getStrong();
|
||||
}
|
||||
@@ -356,26 +401,44 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
|
||||
if (cachedData)
|
||||
{
|
||||
if (shouldReplace())
|
||||
if (shouldReplaceCached())
|
||||
{
|
||||
entry.ptr = data;
|
||||
}
|
||||
else
|
||||
else if constexpr (!replaceCached)
|
||||
{
|
||||
entry.ptr.convertToStrong();
|
||||
data = cachedData;
|
||||
}
|
||||
|
||||
++cache_count_;
|
||||
++cacheCount_;
|
||||
return true;
|
||||
}
|
||||
|
||||
entry.ptr = data;
|
||||
++cache_count_;
|
||||
++cacheCount_;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <
|
||||
class Key,
|
||||
class T,
|
||||
bool IsKeyCache,
|
||||
class SharedWeakUnionPointer,
|
||||
class SharedPointerType,
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
template <class Callback>
|
||||
inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
|
||||
canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback)
|
||||
{
|
||||
return canonicalizeImpl(
|
||||
key, data, detail::ReplaceDynamically{}, std::forward<Callback>(replaceCallback));
|
||||
}
|
||||
|
||||
template <
|
||||
class Key,
|
||||
class T,
|
||||
@@ -389,7 +452,7 @@ inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
|
||||
canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data)
|
||||
{
|
||||
return canonicalize(key, const_cast<SharedPointerType&>(data), []() { return true; });
|
||||
return canonicalizeImpl(key, data, detail::ReplaceCached{});
|
||||
}
|
||||
|
||||
template <
|
||||
@@ -405,7 +468,7 @@ inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
|
||||
canonicalizeReplaceClient(key_type const& key, SharedPointerType& data)
|
||||
{
|
||||
return canonicalize(key, data, []() { return false; });
|
||||
return canonicalizeImpl(key, data, detail::ReplaceClient{});
|
||||
}
|
||||
|
||||
template <
|
||||
@@ -440,7 +503,8 @@ template <
|
||||
template <class ReturnType>
|
||||
inline auto
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
|
||||
insert(key_type const& key, T const& value) -> std::enable_if_t<!IsKeyCache, ReturnType>
|
||||
insert(key_type const& key, T const& value) -> ReturnType
|
||||
requires(!IsKeyCache)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same_v<std::shared_ptr<T>, SharedPointerType> ||
|
||||
@@ -470,14 +534,15 @@ template <
|
||||
template <class ReturnType>
|
||||
inline auto
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
|
||||
insert(key_type const& key) -> std::enable_if_t<IsKeyCache, ReturnType>
|
||||
insert(key_type const& key) -> ReturnType
|
||||
requires IsKeyCache
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
clock_type::time_point const now(clock_.now());
|
||||
auto [it, inserted] = cache_.emplace(
|
||||
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now));
|
||||
if (!inserted)
|
||||
it->second.last_access = now;
|
||||
it->second.lastAccess = now;
|
||||
return inserted;
|
||||
}
|
||||
|
||||
@@ -626,7 +691,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
if (entry.isCached())
|
||||
{
|
||||
// independent of cache size, so not counted as a hit
|
||||
++cache_count_;
|
||||
++cacheCount_;
|
||||
entry.touch(clock_.now());
|
||||
return entry.ptr.getStrong();
|
||||
}
|
||||
@@ -658,7 +723,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
if (total != 0)
|
||||
hitRate = (hits_ * 100) / total;
|
||||
}
|
||||
stats_.hit_rate.set(hitRate);
|
||||
stats_.hitRate.set(hitRate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -676,7 +741,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
sweepHelper(
|
||||
clock_type::time_point const& whenExpire,
|
||||
[[maybe_unused]] clock_type::time_point const& now,
|
||||
typename KeyValueCacheType::map_type& partition,
|
||||
KeyValueCacheType::map_type& partition,
|
||||
SweptPointersVector& stuffToSweep,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::scoped_lock<std::recursive_mutex> const&)
|
||||
@@ -706,7 +771,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
++cit;
|
||||
}
|
||||
}
|
||||
else if (cit->second.last_access <= whenExpire)
|
||||
else if (cit->second.lastAccess <= whenExpire)
|
||||
{
|
||||
// strong, expired
|
||||
++cacheRemovals;
|
||||
@@ -756,7 +821,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
sweepHelper(
|
||||
clock_type::time_point const& whenExpire,
|
||||
clock_type::time_point const& now,
|
||||
typename KeyOnlyCacheType::map_type& partition,
|
||||
KeyOnlyCacheType::map_type& partition,
|
||||
SweptPointersVector&,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::scoped_lock<std::recursive_mutex> const&)
|
||||
@@ -773,12 +838,12 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
auto cit = partition.begin();
|
||||
while (cit != partition.end())
|
||||
{
|
||||
if (cit->second.last_access > now)
|
||||
if (cit->second.lastAccess > now)
|
||||
{
|
||||
cit->second.last_access = now;
|
||||
cit->second.lastAccess = now;
|
||||
++cit;
|
||||
}
|
||||
else if (cit->second.last_access <= whenExpire)
|
||||
else if (cit->second.lastAccess <= whenExpire)
|
||||
{
|
||||
cit = partition.erase(cit);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ namespace xrpl {
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
std::enable_if_t<std::is_arithmetic_v<T>, std::string>
|
||||
std::string
|
||||
to_string(T t) // NOLINT(readability-identifier-naming)
|
||||
requires(std::is_arithmetic_v<T>)
|
||||
{
|
||||
return std::to_string(t);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
#include <xrpl/basics/hardened_hash.h>
|
||||
#include <xrpl/basics/partitioned_unordered_map.h>
|
||||
#include <xrpl/beast/hash/hash_append.h>
|
||||
#include <xrpl/beast/hash/uhash.h>
|
||||
#include <xrpl/beast/hash/xxhasher.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* Use hash_* containers for keys that do not need a cryptographically secure
|
||||
|
||||
@@ -34,8 +34,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -43,7 +45,7 @@ std::string
|
||||
base64Encode(std::uint8_t const* data, std::size_t len);
|
||||
|
||||
inline std::string
|
||||
base64Encode(std::string const& s)
|
||||
base64Encode(std::string_view s)
|
||||
{
|
||||
return base64Encode(reinterpret_cast<std::uint8_t const*>(s.data()), s.size());
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Expected.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/hardened_hash.h>
|
||||
#include <xrpl/basics/partitioned_unordered_map.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/beast/hash/hash_append.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
@@ -19,7 +19,17 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <compare>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <expected>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
@@ -87,7 +97,7 @@ public:
|
||||
//
|
||||
|
||||
static constexpr std::size_t kBytes = Bits / 8;
|
||||
static_assert(sizeof(data_) == kBytes, "");
|
||||
static_assert(sizeof(data_) == kBytes);
|
||||
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@@ -177,7 +187,7 @@ private:
|
||||
BadChar,
|
||||
};
|
||||
|
||||
constexpr Expected<decltype(data_), ParseResult>
|
||||
constexpr std::expected<decltype(data_), ParseResult>
|
||||
parseFromStringView(std::string_view sv) noexcept
|
||||
{
|
||||
// Local lambda that converts a single hex char to four bits and
|
||||
@@ -216,7 +226,7 @@ private:
|
||||
}
|
||||
|
||||
if (sv.size() != size() * 2)
|
||||
return Unexpected(ParseResult::BadLength);
|
||||
return std::unexpected(ParseResult::BadLength);
|
||||
|
||||
std::size_t i = 0u;
|
||||
auto in = sv.begin();
|
||||
@@ -227,7 +237,7 @@ private:
|
||||
{
|
||||
if (auto const result = hexCharToUInt(*in++, shift, accum);
|
||||
result != ParseResult::Okay)
|
||||
return Unexpected(result);
|
||||
return std::unexpected(result);
|
||||
}
|
||||
ret[i++] = accum;
|
||||
}
|
||||
@@ -270,12 +280,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template <
|
||||
class Container,
|
||||
class = std::enable_if_t<
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>>>
|
||||
template <class Container>
|
||||
explicit BaseUInt(Container const& c)
|
||||
requires(
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>)
|
||||
{
|
||||
// Use AlwaysFalseT so the static_assert condition is dependent
|
||||
// and only triggers when this constructor template is instantiated.
|
||||
@@ -285,13 +294,12 @@ public:
|
||||
"Use base_uint::fromRaw instead.");
|
||||
}
|
||||
|
||||
template <
|
||||
class Container,
|
||||
class = std::enable_if_t<
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>>>
|
||||
template <class Container>
|
||||
static BaseUInt
|
||||
fromRaw(Container const& c)
|
||||
requires(
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>)
|
||||
{
|
||||
BaseUInt result;
|
||||
XRPL_ASSERT(
|
||||
@@ -302,11 +310,11 @@ public:
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
std::enable_if_t<
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>,
|
||||
BaseUInt&>
|
||||
BaseUInt&
|
||||
operator=(Container const& c)
|
||||
requires(
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
c.size() * sizeof(typename Container::value_type) == size(),
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <cstdint>
|
||||
#include <ratio>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
/*
|
||||
* MSVC 2019 version 16.9.0 added [[nodiscard]] to the std comparison
|
||||
* operator() functions. boost::bimap checks that the comparator is a
|
||||
* BinaryFunction, in part by calling the function and ignoring the value.
|
||||
* These two things don't play well together. These wrapper classes simply
|
||||
* strip [[nodiscard]] from operator() for use in boost::bimap.
|
||||
*
|
||||
* See also:
|
||||
* https://www.boost.org/doc/libs/1_75_0/libs/bimap/doc/html/boost_bimap/the_tutorial/controlling_collection_types.html
|
||||
*/
|
||||
|
||||
template <class T = void>
|
||||
struct less
|
||||
{
|
||||
using result_type = bool;
|
||||
|
||||
constexpr bool
|
||||
operator()(T const& left, T const& right) const
|
||||
{
|
||||
return std::less<T>()(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = void>
|
||||
struct equal_to
|
||||
{
|
||||
using result_type = bool;
|
||||
|
||||
constexpr bool
|
||||
operator()(T const& left, T const& right) const
|
||||
{
|
||||
return std::equal_to<T>()(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <class T = void>
|
||||
using less = std::less<T>;
|
||||
|
||||
template <class T = void>
|
||||
using equal_to = std::equal_to<T>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/hash/hash_append.h>
|
||||
#include <xrpl/beast/hash/xxhasher.h>
|
||||
|
||||
#include <cstdint>
|
||||
@@ -75,7 +74,7 @@ private:
|
||||
detail::seed_pair seeds_{detail::makeSeedPair<>()};
|
||||
|
||||
public:
|
||||
using result_type = typename HashAlgorithm::result_type;
|
||||
using result_type = HashAlgorithm::result_type;
|
||||
|
||||
HardenedHash() = default;
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <class Stream, class Iter>
|
||||
Stream&
|
||||
join(Stream& s, Iter iter, Iter end, std::string const& delimiter)
|
||||
join(Stream& s, Iter iter, Iter end, std::string_view delimiter)
|
||||
{
|
||||
if (iter == end)
|
||||
return s;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
#include <xrpl/beast/hash/uhash.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
@@ -57,8 +60,8 @@ public:
|
||||
{
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
partition_map_type* map{nullptr};
|
||||
typename partition_map_type::iterator ait{};
|
||||
typename map_type::iterator mit;
|
||||
partition_map_type::iterator ait{};
|
||||
map_type::iterator mit;
|
||||
|
||||
Iterator() = default;
|
||||
|
||||
@@ -126,8 +129,8 @@ public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
partition_map_type* map{nullptr};
|
||||
typename partition_map_type::iterator ait{};
|
||||
typename map_type::iterator mit;
|
||||
partition_map_type::iterator ait{};
|
||||
map_type::iterator mit;
|
||||
|
||||
ConstIterator() = default;
|
||||
|
||||
@@ -135,11 +138,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ConstIterator(Iterator const& orig)
|
||||
ConstIterator(Iterator const& orig) : map(orig.map), ait(orig.ait), mit(orig.mit)
|
||||
{
|
||||
map = orig.map;
|
||||
ait = orig.ait;
|
||||
mit = orig.mit;
|
||||
}
|
||||
|
||||
const_reference
|
||||
@@ -228,11 +228,11 @@ private:
|
||||
|
||||
public:
|
||||
PartitionedUnorderedMap(std::optional<std::size_t> partitions = std::nullopt)
|
||||
{
|
||||
// Set partitions to the number of hardware threads if the parameter
|
||||
// is either empty or set to 0.
|
||||
partitions_ =
|
||||
partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency();
|
||||
: partitions_(
|
||||
partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency())
|
||||
{
|
||||
map_.resize(partitions_);
|
||||
XRPL_ASSERT(
|
||||
partitions_,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/beast/xor_shift_engine.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
@@ -29,6 +28,7 @@ static_assert(
|
||||
namespace detail {
|
||||
|
||||
// Determines if a type can be called like an Engine
|
||||
// NOLINTNEXTLINE(readability-redundant-typename): typename required by MSVC
|
||||
template <class Engine, class Result = typename Engine::result_type>
|
||||
using is_engine = std::is_invocable_r<Result, Engine>;
|
||||
} // namespace detail
|
||||
@@ -91,8 +91,9 @@ defaultPrng()
|
||||
*/
|
||||
/** @{ */
|
||||
template <class Engine, class Integral>
|
||||
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
|
||||
Integral
|
||||
randInt(Engine& engine, Integral min, Integral max)
|
||||
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
|
||||
{
|
||||
XRPL_ASSERT(max > min, "xrpl::randInt : max over min inputs");
|
||||
|
||||
@@ -103,36 +104,41 @@ randInt(Engine& engine, Integral min, Integral max)
|
||||
}
|
||||
|
||||
template <class Integral>
|
||||
std::enable_if_t<std::is_integral_v<Integral>, Integral>
|
||||
Integral
|
||||
randInt(Integral min, Integral max)
|
||||
requires(std::is_integral_v<Integral>)
|
||||
{
|
||||
return randInt(defaultPrng(), min, max);
|
||||
}
|
||||
|
||||
template <class Engine, class Integral>
|
||||
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
|
||||
Integral
|
||||
randInt(Engine& engine, Integral max)
|
||||
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
|
||||
{
|
||||
return randInt(engine, Integral(0), max);
|
||||
}
|
||||
|
||||
template <class Integral>
|
||||
std::enable_if_t<std::is_integral_v<Integral>, Integral>
|
||||
Integral
|
||||
randInt(Integral max)
|
||||
requires(std::is_integral_v<Integral>)
|
||||
{
|
||||
return randInt(defaultPrng(), max);
|
||||
}
|
||||
|
||||
template <class Integral, class Engine>
|
||||
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
|
||||
Integral
|
||||
randInt(Engine& engine)
|
||||
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
|
||||
{
|
||||
return randInt(engine, std::numeric_limits<Integral>::max());
|
||||
}
|
||||
|
||||
template <class Integral = int>
|
||||
std::enable_if_t<std::is_integral_v<Integral>, Integral>
|
||||
Integral
|
||||
randInt()
|
||||
requires(std::is_integral_v<Integral>)
|
||||
{
|
||||
return randInt(defaultPrng(), std::numeric_limits<Integral>::max());
|
||||
}
|
||||
@@ -141,19 +147,20 @@ randInt()
|
||||
/** Return a random byte */
|
||||
/** @{ */
|
||||
template <class Byte, class Engine>
|
||||
std::enable_if_t<
|
||||
(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>) &&
|
||||
detail::is_engine<Engine>::value,
|
||||
Byte>
|
||||
Byte
|
||||
randByte(Engine& engine)
|
||||
requires(
|
||||
(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>) &&
|
||||
detail::is_engine<Engine>::value)
|
||||
{
|
||||
return static_cast<Byte>(randInt<Engine, std::uint32_t>(
|
||||
engine, std::numeric_limits<Byte>::min(), std::numeric_limits<Byte>::max()));
|
||||
}
|
||||
|
||||
template <class Byte = std::uint8_t>
|
||||
std::enable_if_t<(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>), Byte>
|
||||
Byte
|
||||
randByte()
|
||||
requires(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>)
|
||||
{
|
||||
return randByte<Byte>(defaultPrng());
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if XRPL_ROCKSDB_AVAILABLE
|
||||
// #include <rocksdb2/port/port_posix.h>
|
||||
#include <rocksdb/cache.h>
|
||||
#include <rocksdb/compaction_filter.h>
|
||||
#include <rocksdb/comparator.h>
|
||||
#include <rocksdb/convenience.h>
|
||||
#include <rocksdb/db.h>
|
||||
#include <rocksdb/env.h>
|
||||
#include <rocksdb/filter_policy.h>
|
||||
#include <rocksdb/flush_block_policy.h>
|
||||
#include <rocksdb/iterator.h>
|
||||
#include <rocksdb/memtablerep.h>
|
||||
#include <rocksdb/merge_operator.h>
|
||||
#include <rocksdb/options.h>
|
||||
#include <rocksdb/perf_context.h>
|
||||
#include <rocksdb/slice.h>
|
||||
#include <rocksdb/slice_transform.h>
|
||||
#include <rocksdb/statistics.h>
|
||||
#include <rocksdb/status.h>
|
||||
#include <rocksdb/table.h>
|
||||
#include <rocksdb/table_properties.h>
|
||||
#include <rocksdb/transaction_log.h>
|
||||
#include <rocksdb/types.h>
|
||||
#include <rocksdb/universal_compaction.h>
|
||||
#include <rocksdb/write_batch.h>
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h> // IWYU pragma: keep
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
@@ -17,8 +17,9 @@ concept SafeToCast = (std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
|
||||
: sizeof(Dest) >= sizeof(Src));
|
||||
|
||||
template <class Dest, class Src>
|
||||
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
constexpr Dest
|
||||
safeCast(Src s) noexcept
|
||||
requires(std::is_integral_v<Dest> && std::is_integral_v<Src>)
|
||||
{
|
||||
static_assert(
|
||||
std::is_signed_v<Dest> || std::is_unsigned_v<Src>, "Cannot cast signed to unsigned");
|
||||
@@ -30,15 +31,17 @@ safeCast(Src s) noexcept
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
constexpr Dest
|
||||
safeCast(Src s) noexcept
|
||||
requires(std::is_enum_v<Dest> && std::is_integral_v<Src>)
|
||||
{
|
||||
return static_cast<Dest>(safeCast<std::underlying_type_t<Dest>>(s));
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
|
||||
constexpr Dest
|
||||
safeCast(Src s) noexcept
|
||||
requires(std::is_integral_v<Dest> && std::is_enum_v<Src>)
|
||||
{
|
||||
return safeCast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
|
||||
}
|
||||
@@ -48,8 +51,9 @@ safeCast(Src s) noexcept
|
||||
// underlying types become safe, it can be converted to a safe_cast.
|
||||
|
||||
template <class Dest, class Src>
|
||||
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
constexpr Dest
|
||||
unsafeCast(Src s) noexcept
|
||||
requires(std::is_integral_v<Dest> && std::is_integral_v<Src>)
|
||||
{
|
||||
static_assert(
|
||||
!SafeToCast<Src, Dest>,
|
||||
@@ -59,15 +63,17 @@ unsafeCast(Src s) noexcept
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
constexpr Dest
|
||||
unsafeCast(Src s) noexcept
|
||||
requires(std::is_enum_v<Dest> && std::is_integral_v<Src>)
|
||||
{
|
||||
return static_cast<Dest>(unsafeCast<std::underlying_type_t<Dest>>(s));
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
|
||||
constexpr Dest
|
||||
unsafeCast(Src s) noexcept
|
||||
requires(std::is_integral_v<Dest> && std::is_enum_v<Src>)
|
||||
{
|
||||
return unsafeCast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
ASAN flags some false positives with sudden jumps in control flow, like
|
||||
exceptions, or when encountering coroutine stack switches. This macro can be used to disable ASAN
|
||||
intrumentation for specific functions.
|
||||
instrumentation for specific functions.
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define XRPL_NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address", "hwaddress")))
|
||||
|
||||
@@ -24,20 +24,20 @@ namespace xrpl {
|
||||
template <class EF>
|
||||
class ScopeExit
|
||||
{
|
||||
EF exit_function_;
|
||||
bool execute_on_destruction_{true};
|
||||
EF exitFunction_;
|
||||
bool executeOnDestruction_{true};
|
||||
|
||||
public:
|
||||
~ScopeExit()
|
||||
{
|
||||
if (execute_on_destruction_)
|
||||
exit_function_();
|
||||
if (executeOnDestruction_)
|
||||
exitFunction_();
|
||||
}
|
||||
|
||||
ScopeExit(ScopeExit&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
|
||||
: exit_function_{std::forward<EF>(rhs.exit_function_)}
|
||||
, execute_on_destruction_{rhs.execute_on_destruction_}
|
||||
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
|
||||
, executeOnDestruction_{rhs.executeOnDestruction_}
|
||||
{
|
||||
rhs.release();
|
||||
}
|
||||
@@ -46,12 +46,10 @@ public:
|
||||
operator=(ScopeExit&&) = delete;
|
||||
|
||||
template <class EFP>
|
||||
explicit ScopeExit(
|
||||
EFP&& f,
|
||||
std::enable_if_t<
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, ScopeExit> &&
|
||||
std::is_constructible_v<EF, EFP>>* = 0) noexcept
|
||||
: exit_function_{std::forward<EFP>(f)}
|
||||
explicit ScopeExit(EFP&& f) noexcept
|
||||
requires(
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, ScopeExit> && std::is_constructible_v<EF, EFP>)
|
||||
: exitFunction_{std::forward<EFP>(f)}
|
||||
{
|
||||
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
|
||||
}
|
||||
@@ -59,7 +57,7 @@ public:
|
||||
void
|
||||
release() noexcept
|
||||
{
|
||||
execute_on_destruction_ = false;
|
||||
executeOnDestruction_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,22 +67,22 @@ ScopeExit(EF) -> ScopeExit<EF>;
|
||||
template <class EF>
|
||||
class ScopeFail
|
||||
{
|
||||
EF exit_function_;
|
||||
bool execute_on_destruction_{true};
|
||||
int uncaught_on_creation_{std::uncaught_exceptions()};
|
||||
EF exitFunction_;
|
||||
bool executeOnDestruction_{true};
|
||||
int uncaughtOnCreation_{std::uncaught_exceptions()};
|
||||
|
||||
public:
|
||||
~ScopeFail()
|
||||
{
|
||||
if (execute_on_destruction_ && std::uncaught_exceptions() > uncaught_on_creation_)
|
||||
exit_function_();
|
||||
if (executeOnDestruction_ && std::uncaught_exceptions() > uncaughtOnCreation_)
|
||||
exitFunction_();
|
||||
}
|
||||
|
||||
ScopeFail(ScopeFail&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
|
||||
: exit_function_{std::forward<EF>(rhs.exit_function_)}
|
||||
, execute_on_destruction_{rhs.execute_on_destruction_}
|
||||
, uncaught_on_creation_{rhs.uncaught_on_creation_}
|
||||
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
|
||||
, executeOnDestruction_{rhs.executeOnDestruction_}
|
||||
, uncaughtOnCreation_{rhs.uncaughtOnCreation_}
|
||||
{
|
||||
rhs.release();
|
||||
}
|
||||
@@ -93,12 +91,10 @@ public:
|
||||
operator=(ScopeFail&&) = delete;
|
||||
|
||||
template <class EFP>
|
||||
explicit ScopeFail(
|
||||
EFP&& f,
|
||||
std::enable_if_t<
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, ScopeFail> &&
|
||||
std::is_constructible_v<EF, EFP>>* = 0) noexcept
|
||||
: exit_function_{std::forward<EFP>(f)}
|
||||
explicit ScopeFail(EFP&& f) noexcept
|
||||
requires(
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, ScopeFail> && std::is_constructible_v<EF, EFP>)
|
||||
: exitFunction_{std::forward<EFP>(f)}
|
||||
{
|
||||
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
|
||||
}
|
||||
@@ -106,7 +102,7 @@ public:
|
||||
void
|
||||
release() noexcept
|
||||
{
|
||||
execute_on_destruction_ = false;
|
||||
executeOnDestruction_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -116,22 +112,22 @@ ScopeFail(EF) -> ScopeFail<EF>;
|
||||
template <class EF>
|
||||
class ScopeSuccess
|
||||
{
|
||||
EF exit_function_;
|
||||
bool execute_on_destruction_{true};
|
||||
int uncaught_on_creation_{std::uncaught_exceptions()};
|
||||
EF exitFunction_;
|
||||
bool executeOnDestruction_{true};
|
||||
int uncaughtOnCreation_{std::uncaught_exceptions()};
|
||||
|
||||
public:
|
||||
~ScopeSuccess() noexcept(noexcept(exit_function_()))
|
||||
~ScopeSuccess() noexcept(noexcept(exitFunction_()))
|
||||
{
|
||||
if (execute_on_destruction_ && std::uncaught_exceptions() <= uncaught_on_creation_)
|
||||
exit_function_();
|
||||
if (executeOnDestruction_ && std::uncaught_exceptions() <= uncaughtOnCreation_)
|
||||
exitFunction_();
|
||||
}
|
||||
|
||||
ScopeSuccess(ScopeSuccess&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
|
||||
: exit_function_{std::forward<EF>(rhs.exit_function_)}
|
||||
, execute_on_destruction_{rhs.execute_on_destruction_}
|
||||
, uncaught_on_creation_{rhs.uncaught_on_creation_}
|
||||
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
|
||||
, executeOnDestruction_{rhs.executeOnDestruction_}
|
||||
, uncaughtOnCreation_{rhs.uncaughtOnCreation_}
|
||||
{
|
||||
rhs.release();
|
||||
}
|
||||
@@ -140,20 +136,19 @@ public:
|
||||
operator=(ScopeSuccess&&) = delete;
|
||||
|
||||
template <class EFP>
|
||||
explicit ScopeSuccess(
|
||||
EFP&& f,
|
||||
std::enable_if_t<
|
||||
explicit ScopeSuccess(EFP&& f) noexcept(
|
||||
std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
|
||||
requires(
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, ScopeSuccess> &&
|
||||
std::is_constructible_v<EF, EFP>>* =
|
||||
0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
|
||||
: exit_function_{std::forward<EFP>(f)}
|
||||
std::is_constructible_v<EF, EFP>)
|
||||
: exitFunction_{std::forward<EFP>(f)}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept
|
||||
{
|
||||
execute_on_destruction_ = false;
|
||||
executeOnDestruction_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/endian/conversion.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <class FwdIt>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
@@ -42,10 +43,10 @@ public:
|
||||
|
||||
TaggedInteger() = default;
|
||||
|
||||
template <
|
||||
class OtherInt,
|
||||
class = std::enable_if_t<std::is_integral_v<OtherInt> && sizeof(OtherInt) <= sizeof(Int)>>
|
||||
explicit constexpr TaggedInteger(OtherInt value) noexcept : value_(value)
|
||||
template <class OtherInt>
|
||||
explicit constexpr TaggedInteger(OtherInt value) noexcept
|
||||
requires(std::is_integral_v<OtherInt> && sizeof(OtherInt) <= sizeof(Int))
|
||||
: value_(value)
|
||||
{
|
||||
static_assert(sizeof(TaggedInteger) == sizeof(Int), "tagged_integer is adding padding");
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -18,8 +19,8 @@ template <class Clock>
|
||||
class IOLatencyProbe
|
||||
{
|
||||
private:
|
||||
using duration = typename Clock::duration;
|
||||
using time_point = typename Clock::time_point;
|
||||
using duration = Clock::duration;
|
||||
using time_point = Clock::time_point;
|
||||
|
||||
std::recursive_mutex mutex_;
|
||||
std::condition_variable_any cond_;
|
||||
|
||||
@@ -34,10 +34,10 @@ template <class Clock>
|
||||
class AbstractClock
|
||||
{
|
||||
public:
|
||||
using rep = typename Clock::rep;
|
||||
using period = typename Clock::period;
|
||||
using duration = typename Clock::duration;
|
||||
using time_point = typename Clock::time_point;
|
||||
using rep = Clock::rep;
|
||||
using period = Clock::period;
|
||||
using duration = Clock::duration;
|
||||
using time_point = Clock::time_point;
|
||||
using clock_type = Clock;
|
||||
|
||||
static bool const is_steady = Clock::is_steady; // NOLINT(readability-identifier-naming)
|
||||
|
||||
@@ -20,10 +20,10 @@ public:
|
||||
|
||||
explicit BasicSecondsClock() = default;
|
||||
|
||||
using rep = typename Clock::rep;
|
||||
using period = typename Clock::period;
|
||||
using duration = typename Clock::duration;
|
||||
using time_point = typename Clock::time_point;
|
||||
using rep = Clock::rep;
|
||||
using period = Clock::period;
|
||||
using duration = Clock::duration;
|
||||
using time_point = Clock::time_point;
|
||||
|
||||
static bool const is_steady = // NOLINT(readability-identifier-naming)
|
||||
Clock::is_steady;
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
#include <xrpl/beast/container/aged_container.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Expire aged container items past the specified age. */
|
||||
template <class AgedContainer, class Rep, class Period>
|
||||
std::enable_if_t<IsAgedContainer<AgedContainer>::value, std::size_t>
|
||||
std::size_t
|
||||
expire(AgedContainer& c, std::chrono::duration<Rep, Period> const& age)
|
||||
requires(IsAgedContainer<AgedContainer>::value)
|
||||
{
|
||||
std::size_t n(0);
|
||||
auto const expired(c.clock().now() - age);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
|
||||
@@ -16,34 +16,33 @@ template <bool IsConst, class Iterator>
|
||||
class AgedContainerIterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
|
||||
using iterator_category = std::iterator_traits<Iterator>::iterator_category;
|
||||
using value_type = std::conditional_t<
|
||||
IsConst,
|
||||
typename Iterator::value_type::Stashed::value_type const,
|
||||
typename Iterator::value_type::Stashed::value_type>;
|
||||
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
|
||||
using difference_type = std::iterator_traits<Iterator>::difference_type;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
using time_point = typename Iterator::value_type::Stashed::time_point;
|
||||
using time_point = Iterator::value_type::Stashed::time_point;
|
||||
|
||||
AgedContainerIterator() = default;
|
||||
|
||||
// Disable constructing a const_iterator from a non-const_iterator.
|
||||
// Converting between reverse and non-reverse iterators should be explicit.
|
||||
template <
|
||||
bool OtherIsConst,
|
||||
class OtherIterator,
|
||||
class = std::enable_if_t<
|
||||
(!OtherIsConst || IsConst) &&
|
||||
!static_cast<bool>(std::is_same_v<Iterator, OtherIterator>)>>
|
||||
template <bool OtherIsConst, class OtherIterator>
|
||||
explicit AgedContainerIterator(AgedContainerIterator<OtherIsConst, OtherIterator> const& other)
|
||||
requires(
|
||||
(!OtherIsConst || IsConst) &&
|
||||
!static_cast<bool>(std::is_same_v<Iterator, OtherIterator>))
|
||||
: iter_(other.iter_)
|
||||
{
|
||||
}
|
||||
|
||||
// Disable constructing a const_iterator from a non-const_iterator.
|
||||
template <bool OtherIsConst, class = std::enable_if_t<!OtherIsConst || IsConst>>
|
||||
template <bool OtherIsConst>
|
||||
AgedContainerIterator(AgedContainerIterator<OtherIsConst, Iterator> const& other)
|
||||
requires(!OtherIsConst || IsConst)
|
||||
: iter_(other.iter_)
|
||||
{
|
||||
}
|
||||
@@ -52,7 +51,8 @@ public:
|
||||
template <bool OtherIsConst, class OtherIterator>
|
||||
auto
|
||||
operator=(AgedContainerIterator<OtherIsConst, OtherIterator> const& other)
|
||||
-> std::enable_if_t<!OtherIsConst || IsConst, AgedContainerIterator&>
|
||||
-> AgedContainerIterator&
|
||||
requires(!OtherIsConst || IsConst)
|
||||
{
|
||||
iter_ = other.iter_;
|
||||
return *this;
|
||||
|
||||
@@ -11,9 +11,14 @@
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -62,8 +67,8 @@ class AgedOrderedContainer
|
||||
{
|
||||
public:
|
||||
using clock_type = AbstractClock<Clock>;
|
||||
using time_point = typename clock_type::time_point;
|
||||
using duration = typename clock_type::duration;
|
||||
using time_point = clock_type::time_point;
|
||||
using duration = clock_type::duration;
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using value_type = std::conditional_t<IsMap, std::pair<Key const, T>, Key>;
|
||||
@@ -94,8 +99,8 @@ private:
|
||||
{
|
||||
explicit Stashed() = default;
|
||||
|
||||
using value_type = typename AgedOrderedContainer::value_type;
|
||||
using time_point = typename AgedOrderedContainer::time_point;
|
||||
using value_type = AgedOrderedContainer::value_type;
|
||||
using time_point = AgedOrderedContainer::time_point;
|
||||
};
|
||||
|
||||
Element(time_point const& when, value_type const& value) : value(value), when(when)
|
||||
@@ -106,10 +111,9 @@ private:
|
||||
{
|
||||
}
|
||||
|
||||
template <
|
||||
class... Args,
|
||||
class = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
|
||||
template <class... Args>
|
||||
Element(time_point const& when, Args&&... args)
|
||||
requires(std::is_constructible_v<value_type, Args...>)
|
||||
: value(std::forward<Args>(args)...), when(when)
|
||||
{
|
||||
}
|
||||
@@ -192,8 +196,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
using list_type = typename boost::intrusive::
|
||||
make_list<Element, boost::intrusive::constant_time_size<false>>::type;
|
||||
using list_type =
|
||||
boost::intrusive::make_list<Element, boost::intrusive::constant_time_size<false>>::type;
|
||||
|
||||
using cont_type = std::conditional_t<
|
||||
IsMulti,
|
||||
@@ -206,8 +210,7 @@ private:
|
||||
boost::intrusive::constant_time_size<true>,
|
||||
boost::intrusive::compare<KeyValueCompare>>::type>;
|
||||
|
||||
using ElementAllocator =
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
|
||||
using ElementAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
|
||||
|
||||
using ElementAllocatorTraits = std::allocator_traits<ElementAllocator>;
|
||||
|
||||
@@ -356,6 +359,7 @@ private:
|
||||
deleteElement(Element const* p)
|
||||
{
|
||||
ElementAllocatorTraits::destroy(config_.alloc(), p);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
ElementAllocatorTraits::deallocate(config_.alloc(), const_cast<Element*>(p), 1);
|
||||
}
|
||||
|
||||
@@ -373,8 +377,8 @@ public:
|
||||
using allocator_type = Allocator;
|
||||
using reference = value_type&;
|
||||
using const_reference = value_type const&;
|
||||
using pointer = typename std::allocator_traits<Allocator>::pointer;
|
||||
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
|
||||
using pointer = std::allocator_traits<Allocator>::pointer;
|
||||
using const_pointer = std::allocator_traits<Allocator>::const_pointer;
|
||||
|
||||
// A set iterator (IsMap==false) is always const
|
||||
// because the elements of a set are immutable.
|
||||
@@ -604,35 +608,25 @@ public:
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
class K,
|
||||
bool MaybeMulti = IsMulti,
|
||||
bool MaybeMap = IsMap,
|
||||
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
|
||||
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
at(K const& k);
|
||||
at(K const& k)
|
||||
requires(MaybeMap && !MaybeMulti);
|
||||
|
||||
template <
|
||||
class K,
|
||||
bool MaybeMulti = IsMulti,
|
||||
bool MaybeMap = IsMap,
|
||||
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
|
||||
typename std::conditional<IsMap, T, void*>::type const&
|
||||
at(K const& k) const;
|
||||
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
std::conditional<IsMap, T, void*>::type const&
|
||||
at(K const& k) const
|
||||
requires(MaybeMap && !MaybeMulti);
|
||||
|
||||
template <
|
||||
bool MaybeMulti = IsMulti,
|
||||
bool MaybeMap = IsMap,
|
||||
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
|
||||
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
operator[](Key const& key);
|
||||
operator[](Key const& key)
|
||||
requires(MaybeMap && !MaybeMulti);
|
||||
|
||||
template <
|
||||
bool MaybeMulti = IsMulti,
|
||||
bool MaybeMap = IsMap,
|
||||
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
|
||||
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
operator[](Key&& key);
|
||||
operator[](Key&& key)
|
||||
requires(MaybeMap && !MaybeMulti);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
@@ -766,35 +760,40 @@ public:
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
auto
|
||||
insert(value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
|
||||
insert(value_type const& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multimap, multiset
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
auto
|
||||
insert(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
|
||||
insert(value_type const& value) -> iterator
|
||||
requires MaybeMulti;
|
||||
|
||||
// set
|
||||
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
auto
|
||||
insert(value_type&& value)
|
||||
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>;
|
||||
insert(value_type&& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti && !MaybeMap);
|
||||
|
||||
// multiset
|
||||
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
auto
|
||||
insert(value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>;
|
||||
insert(value_type&& value) -> iterator
|
||||
requires(MaybeMulti && !MaybeMap);
|
||||
|
||||
//---
|
||||
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
auto
|
||||
insert(const_iterator hint, value_type const& value) -> std::enable_if_t<!MaybeMulti, iterator>;
|
||||
insert(const_iterator hint, value_type const& value) -> iterator
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multimap, multiset
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
std::enable_if_t<MaybeMulti, iterator>
|
||||
iterator
|
||||
insert(const_iterator /*hint*/, value_type const& value)
|
||||
requires MaybeMulti
|
||||
{
|
||||
// VFALCO TODO Figure out how to utilize 'hint'
|
||||
return insert(value);
|
||||
@@ -803,12 +802,14 @@ public:
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
auto
|
||||
insert(const_iterator hint, value_type&& value) -> std::enable_if_t<!MaybeMulti, iterator>;
|
||||
insert(const_iterator hint, value_type&& value) -> iterator
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multimap, multiset
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
std::enable_if_t<MaybeMulti, iterator>
|
||||
iterator
|
||||
insert(const_iterator /*hint*/, value_type&& value)
|
||||
requires MaybeMulti
|
||||
{
|
||||
// VFALCO TODO Figure out how to utilize 'hint'
|
||||
return insert(std::move(value));
|
||||
@@ -816,20 +817,18 @@ public:
|
||||
|
||||
// map, multimap
|
||||
template <class P, bool MaybeMap = IsMap>
|
||||
std::enable_if_t<
|
||||
MaybeMap && std::is_constructible_v<value_type, P&&>,
|
||||
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
|
||||
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
|
||||
insert(P&& value)
|
||||
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
|
||||
{
|
||||
return emplace(std::forward<P>(value));
|
||||
}
|
||||
|
||||
// map, multimap
|
||||
template <class P, bool MaybeMap = IsMap>
|
||||
std::enable_if_t<
|
||||
MaybeMap && std::is_constructible_v<value_type, P&&>,
|
||||
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
|
||||
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
|
||||
insert(const_iterator hint, P&& value)
|
||||
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
|
||||
{
|
||||
return emplaceHint(hint, std::forward<P>(value));
|
||||
}
|
||||
@@ -851,46 +850,45 @@ public:
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti, class... Args>
|
||||
auto
|
||||
emplace(Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
|
||||
emplace(Args&&... args) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multiset, multimap
|
||||
template <bool MaybeMulti = IsMulti, class... Args>
|
||||
auto
|
||||
emplace(Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>;
|
||||
emplace(Args&&... args) -> iterator
|
||||
requires MaybeMulti;
|
||||
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti, class... Args>
|
||||
auto
|
||||
emplaceHint(const_iterator hint, Args&&... args)
|
||||
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
|
||||
emplaceHint(const_iterator hint, Args&&... args) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multiset, multimap
|
||||
template <bool MaybeMulti = IsMulti, class... Args>
|
||||
std::enable_if_t<MaybeMulti, iterator>
|
||||
iterator
|
||||
emplaceHint(const_iterator /*hint*/, Args&&... args)
|
||||
requires MaybeMulti
|
||||
{
|
||||
// VFALCO TODO Figure out how to utilize 'hint'
|
||||
return emplace<MaybeMulti>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// enable_if prevents erase (reverse_iterator pos) from compiling
|
||||
template <
|
||||
bool IsConst,
|
||||
class Iterator,
|
||||
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
|
||||
// The constraint prevents erase (reverse_iterator pos) from compiling
|
||||
template <bool IsConst, class Iterator>
|
||||
beast::detail::AgedContainerIterator<false, Iterator>
|
||||
erase(beast::detail::AgedContainerIterator<IsConst, Iterator> pos);
|
||||
erase(beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
|
||||
requires(!IsBoostReverseIterator<Iterator>::value);
|
||||
|
||||
// enable_if prevents erase (reverse_iterator first, reverse_iterator last)
|
||||
// The constraint prevents erase (reverse_iterator first, reverse_iterator last)
|
||||
// from compiling
|
||||
template <
|
||||
bool IsConst,
|
||||
class Iterator,
|
||||
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
|
||||
template <bool IsConst, class Iterator>
|
||||
beast::detail::AgedContainerIterator<false, Iterator>
|
||||
erase(
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> first,
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> last);
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> last)
|
||||
requires(!IsBoostReverseIterator<Iterator>::value);
|
||||
|
||||
template <class K>
|
||||
auto
|
||||
@@ -901,13 +899,11 @@ public:
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// enable_if prevents touch (reverse_iterator pos) from compiling
|
||||
template <
|
||||
bool IsConst,
|
||||
class Iterator,
|
||||
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
|
||||
// The constraint prevents touch (reverse_iterator pos) from compiling
|
||||
template <bool IsConst, class Iterator>
|
||||
void
|
||||
touch(beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
|
||||
requires(!IsBoostReverseIterator<Iterator>::value)
|
||||
{
|
||||
touch(pos, clock().now());
|
||||
}
|
||||
@@ -1138,25 +1134,25 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// enable_if prevents erase (reverse_iterator pos, now) from compiling
|
||||
template <
|
||||
bool IsConst,
|
||||
class Iterator,
|
||||
class = std::enable_if_t<!IsBoostReverseIterator<Iterator>::value>>
|
||||
// The constraint prevents erase (reverse_iterator pos, now) from compiling
|
||||
template <bool IsConst, class Iterator>
|
||||
void
|
||||
touch(
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
|
||||
typename clock_type::time_point const& now);
|
||||
clock_type::time_point const& now)
|
||||
requires(!IsBoostReverseIterator<Iterator>::value);
|
||||
|
||||
template <
|
||||
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
|
||||
std::enable_if_t<MaybePropagate>
|
||||
swapData(AgedOrderedContainer& other) noexcept;
|
||||
void
|
||||
swapData(AgedOrderedContainer& other) noexcept
|
||||
requires MaybePropagate;
|
||||
|
||||
template <
|
||||
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
|
||||
std::enable_if_t<!MaybePropagate>
|
||||
swapData(AgedOrderedContainer& other) noexcept;
|
||||
void
|
||||
swapData(AgedOrderedContainer& other) noexcept
|
||||
requires(!MaybePropagate);
|
||||
|
||||
private:
|
||||
ConfigT config_;
|
||||
@@ -1248,12 +1244,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrd
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
|
||||
AgedOrderedContainer const& other)
|
||||
: config_(other.config_)
|
||||
#if BOOST_VERSION >= 108000
|
||||
, cont_(other.cont_.get_comp())
|
||||
#else
|
||||
, cont_(other.cont_.comp())
|
||||
#endif
|
||||
: config_(other.config_), cont_(other.cont_.get_comp())
|
||||
{
|
||||
insert(other.cbegin(), other.cend());
|
||||
}
|
||||
@@ -1262,12 +1253,7 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
|
||||
AgedOrderedContainer const& other,
|
||||
Allocator const& alloc)
|
||||
: config_(other.config_, alloc)
|
||||
#if BOOST_VERSION >= 108000
|
||||
, cont_(other.cont_.get_comp())
|
||||
#else
|
||||
, cont_(other.cont_.comp())
|
||||
#endif
|
||||
: config_(other.config_, alloc), cont_(other.cont_.get_comp())
|
||||
{
|
||||
insert(other.cbegin(), other.cend());
|
||||
}
|
||||
@@ -1284,13 +1270,7 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
|
||||
AgedOrderedContainer&& other, // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
|
||||
Allocator const& alloc)
|
||||
: config_(std::move(other.config_), alloc)
|
||||
#if BOOST_VERSION >= 108000
|
||||
, cont_(std::move(other.cont_.get_comp()))
|
||||
#else
|
||||
, cont_(std::move(other.cont_.comp()))
|
||||
#endif
|
||||
|
||||
: config_(std::move(other.config_), alloc), cont_(std::move(other.cont_.get_comp()))
|
||||
{
|
||||
insert(other.cbegin(), other.cend());
|
||||
other.clear();
|
||||
@@ -1381,9 +1361,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <class K, bool MaybeMulti, bool MaybeMap, class>
|
||||
template <class K, bool MaybeMulti, bool MaybeMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K const& k)
|
||||
requires(MaybeMap && !MaybeMulti)
|
||||
{
|
||||
auto const iter(cont_.find(k, std::cref(config_.keyCompare())));
|
||||
if (iter == cont_.end())
|
||||
@@ -1392,9 +1373,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K co
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <class K, bool MaybeMulti, bool MaybeMap, class>
|
||||
typename std::conditional<IsMap, T, void*>::type const&
|
||||
template <class K, bool MaybeMulti, bool MaybeMap>
|
||||
std::conditional<IsMap, T, void*>::type const&
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K const& k) const
|
||||
requires(MaybeMap && !MaybeMulti)
|
||||
{
|
||||
auto const iter(cont_.find(k, std::cref(config_.keyCompare())));
|
||||
if (iter == cont_.end())
|
||||
@@ -1403,9 +1385,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K co
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <bool MaybeMulti, bool MaybeMap, class>
|
||||
template <bool MaybeMulti, bool MaybeMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key const& key)
|
||||
requires(MaybeMap && !MaybeMulti)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
auto const result(cont_.insert_check(key, std::cref(config_.keyCompare()), d));
|
||||
@@ -1421,9 +1404,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <bool MaybeMulti, bool MaybeMap, class>
|
||||
template <bool MaybeMulti, bool MaybeMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key&& key)
|
||||
requires(MaybeMap && !MaybeMulti)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
auto const result(cont_.insert_check(key, std::cref(config_.keyCompare()), d));
|
||||
@@ -1457,7 +1441,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
|
||||
template <bool MaybeMulti>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
|
||||
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
|
||||
value_type const& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
auto const result(cont_.insert_check(extract(value), std::cref(config_.keyCompare()), d));
|
||||
@@ -1476,7 +1461,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
|
||||
template <bool MaybeMulti>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
|
||||
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
|
||||
value_type const& value) -> iterator
|
||||
requires MaybeMulti
|
||||
{
|
||||
auto const before(cont_.upper_bound(extract(value), std::cref(config_.keyCompare())));
|
||||
Element* const p(newElement(value));
|
||||
@@ -1490,7 +1476,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
|
||||
template <bool MaybeMulti, bool MaybeMap>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type&& value)
|
||||
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>
|
||||
-> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti && !MaybeMap)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
auto const result(cont_.insert_check(extract(value), std::cref(config_.keyCompare()), d));
|
||||
@@ -1509,7 +1496,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
|
||||
template <bool MaybeMulti, bool MaybeMap>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(value_type&& value)
|
||||
-> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>
|
||||
-> iterator
|
||||
requires(MaybeMulti && !MaybeMap)
|
||||
{
|
||||
auto const before(cont_.upper_bound(extract(value), std::cref(config_.keyCompare())));
|
||||
Element* const p(newElement(std::move(value)));
|
||||
@@ -1526,7 +1514,8 @@ template <bool MaybeMulti>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
|
||||
const_iterator hint,
|
||||
value_type const& value) -> std::enable_if_t<!MaybeMulti, iterator>
|
||||
value_type const& value) -> iterator
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
auto const result(
|
||||
@@ -1547,7 +1536,8 @@ template <bool MaybeMulti>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
|
||||
const_iterator hint,
|
||||
value_type&& value) -> std::enable_if_t<!MaybeMulti, iterator>
|
||||
value_type&& value) -> iterator
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
auto const result(
|
||||
@@ -1567,7 +1557,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
|
||||
template <bool MaybeMulti, class... Args>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args)
|
||||
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
|
||||
-> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
// VFALCO NOTE Its unfortunate that we need to
|
||||
// construct element here
|
||||
@@ -1589,7 +1580,8 @@ template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compa
|
||||
template <bool MaybeMulti, class... Args>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace(Args&&... args)
|
||||
-> std::enable_if_t<MaybeMulti, iterator>
|
||||
-> iterator
|
||||
requires MaybeMulti
|
||||
{
|
||||
Element* const p(newElement(std::forward<Args>(args)...));
|
||||
auto const before(cont_.upper_bound(extract(p->value), std::cref(config_.keyCompare())));
|
||||
@@ -1604,7 +1596,8 @@ template <bool MaybeMulti, class... Args>
|
||||
auto
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplaceHint(
|
||||
const_iterator hint,
|
||||
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
|
||||
Args&&... args) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
// VFALCO NOTE Its unfortunate that we need to
|
||||
// construct element here
|
||||
@@ -1623,21 +1616,23 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <bool IsConst, class Iterator, class>
|
||||
template <bool IsConst, class Iterator>
|
||||
beast::detail::AgedContainerIterator<false, Iterator>
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
|
||||
requires(!IsBoostReverseIterator<Iterator>::value)
|
||||
{
|
||||
unlinkAndDeleteElement(&*((pos++).iterator()));
|
||||
return beast::detail::AgedContainerIterator<false, Iterator>(pos.iterator());
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <bool IsConst, class Iterator, class>
|
||||
template <bool IsConst, class Iterator>
|
||||
beast::detail::AgedContainerIterator<false, Iterator>
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> first,
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> last)
|
||||
requires(!IsBoostReverseIterator<Iterator>::value)
|
||||
{
|
||||
for (; first != last;)
|
||||
unlinkAndDeleteElement(&*((first++).iterator()));
|
||||
@@ -1732,7 +1727,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
|
||||
cend(),
|
||||
other.cbegin(),
|
||||
other.cend(),
|
||||
[&eq, &other](value_type const& lhs, typename Other::value_type const& rhs) {
|
||||
[&eq, &other](value_type const& lhs, Other::value_type const& rhs) {
|
||||
return eq(extract(lhs), other.extract(rhs));
|
||||
});
|
||||
}
|
||||
@@ -1740,11 +1735,12 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <bool IsConst, class Iterator, class>
|
||||
template <bool IsConst, class Iterator>
|
||||
void
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
|
||||
typename clock_type::time_point const& now)
|
||||
clock_type::time_point const& now)
|
||||
requires(!IsBoostReverseIterator<Iterator>::value)
|
||||
{
|
||||
auto& e(*pos.iterator());
|
||||
e.when = now;
|
||||
@@ -1754,9 +1750,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <bool MaybePropagate>
|
||||
std::enable_if_t<MaybePropagate>
|
||||
void
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapData(
|
||||
AgedOrderedContainer& other) noexcept
|
||||
requires MaybePropagate
|
||||
{
|
||||
std::swap(config_.keyCompare(), other.config_.keyCompare());
|
||||
std::swap(config_.alloc(), other.config_.alloc());
|
||||
@@ -1765,9 +1762,10 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapDat
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
|
||||
template <bool MaybePropagate>
|
||||
std::enable_if_t<!MaybePropagate>
|
||||
void
|
||||
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::swapData(
|
||||
AgedOrderedContainer& other) noexcept
|
||||
requires(!MaybePropagate)
|
||||
{
|
||||
std::swap(config_.keyCompare(), other.config_.keyCompare());
|
||||
std::swap(config_.clock, other.config_.clock);
|
||||
|
||||
@@ -10,13 +10,19 @@
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
|
||||
@@ -67,8 +73,8 @@ class AgedUnorderedContainer
|
||||
{
|
||||
public:
|
||||
using clock_type = AbstractClock<Clock>;
|
||||
using time_point = typename clock_type::time_point;
|
||||
using duration = typename clock_type::duration;
|
||||
using time_point = clock_type::time_point;
|
||||
using duration = clock_type::duration;
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using value_type = std::conditional_t<IsMap, std::pair<Key const, T>, Key>;
|
||||
@@ -99,8 +105,8 @@ private:
|
||||
{
|
||||
explicit Stashed() = default;
|
||||
|
||||
using value_type = typename AgedUnorderedContainer::value_type;
|
||||
using time_point = typename AgedUnorderedContainer::time_point;
|
||||
using value_type = AgedUnorderedContainer::value_type;
|
||||
using time_point = AgedUnorderedContainer::time_point;
|
||||
};
|
||||
|
||||
Element(time_point const& when, value_type const& value) : value(value), when(when)
|
||||
@@ -111,10 +117,9 @@ private:
|
||||
{
|
||||
}
|
||||
|
||||
template <
|
||||
class... Args,
|
||||
class = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
|
||||
template <class... Args>
|
||||
Element(time_point const& when, Args&&... args)
|
||||
requires(std::is_constructible_v<value_type, Args...>)
|
||||
: value(std::forward<Args>(args)...), when(when)
|
||||
{
|
||||
}
|
||||
@@ -201,8 +206,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
using list_type = typename boost::intrusive::
|
||||
make_list<Element, boost::intrusive::constant_time_size<false>>::type;
|
||||
using list_type =
|
||||
boost::intrusive::make_list<Element, boost::intrusive::constant_time_size<false>>::type;
|
||||
|
||||
using cont_type = std::conditional_t<
|
||||
IsMulti,
|
||||
@@ -219,16 +224,14 @@ private:
|
||||
boost::intrusive::equal<KeyValueEqual>,
|
||||
boost::intrusive::cache_begin<true>>::type>;
|
||||
|
||||
using bucket_type = typename cont_type::bucket_type;
|
||||
using bucket_traits = typename cont_type::bucket_traits;
|
||||
using bucket_type = cont_type::bucket_type;
|
||||
using bucket_traits = cont_type::bucket_traits;
|
||||
|
||||
using ElementAllocator =
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
|
||||
using ElementAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
|
||||
|
||||
using ElementAllocatorTraits = std::allocator_traits<ElementAllocator>;
|
||||
|
||||
using BucketAllocator =
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
|
||||
using BucketAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
|
||||
|
||||
using BucketAllocatorTraits = std::allocator_traits<BucketAllocator>;
|
||||
|
||||
@@ -525,6 +528,7 @@ private:
|
||||
deleteElement(Element const* p)
|
||||
{
|
||||
ElementAllocatorTraits::destroy(config_.alloc(), p);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
ElementAllocatorTraits::deallocate(config_.alloc(), const_cast<Element*>(p), 1);
|
||||
}
|
||||
|
||||
@@ -542,8 +546,8 @@ public:
|
||||
using allocator_type = Allocator;
|
||||
using reference = value_type&;
|
||||
using const_reference = value_type const&;
|
||||
using pointer = typename std::allocator_traits<Allocator>::pointer;
|
||||
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
|
||||
using pointer = std::allocator_traits<Allocator>::pointer;
|
||||
using const_pointer = std::allocator_traits<Allocator>::const_pointer;
|
||||
|
||||
// A set iterator (IsMap==false) is always const
|
||||
// because the elements of a set are immutable.
|
||||
@@ -837,35 +841,25 @@ public:
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
class K,
|
||||
bool MaybeMulti = IsMulti,
|
||||
bool MaybeMap = IsMap,
|
||||
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
|
||||
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
at(K const& k);
|
||||
at(K const& k)
|
||||
requires(MaybeMap && !MaybeMulti);
|
||||
|
||||
template <
|
||||
class K,
|
||||
bool MaybeMulti = IsMulti,
|
||||
bool MaybeMap = IsMap,
|
||||
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
|
||||
typename std::conditional<IsMap, T, void*>::type const&
|
||||
at(K const& k) const;
|
||||
template <class K, bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
std::conditional<IsMap, T, void*>::type const&
|
||||
at(K const& k) const
|
||||
requires(MaybeMap && !MaybeMulti);
|
||||
|
||||
template <
|
||||
bool MaybeMulti = IsMulti,
|
||||
bool MaybeMap = IsMap,
|
||||
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
|
||||
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
operator[](Key const& key);
|
||||
operator[](Key const& key)
|
||||
requires(MaybeMap && !MaybeMulti);
|
||||
|
||||
template <
|
||||
bool MaybeMulti = IsMulti,
|
||||
bool MaybeMap = IsMap,
|
||||
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
|
||||
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
operator[](Key&& key);
|
||||
operator[](Key&& key)
|
||||
requires(MaybeMap && !MaybeMulti);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
@@ -963,28 +957,32 @@ public:
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
auto
|
||||
insert(value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
|
||||
insert(value_type const& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multimap, multiset
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
auto
|
||||
insert(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
|
||||
insert(value_type const& value) -> iterator
|
||||
requires MaybeMulti;
|
||||
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
auto
|
||||
insert(value_type&& value)
|
||||
-> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>;
|
||||
insert(value_type&& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti && !MaybeMap);
|
||||
|
||||
// multimap, multiset
|
||||
template <bool MaybeMulti = IsMulti, bool MaybeMap = IsMap>
|
||||
auto
|
||||
insert(value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>;
|
||||
insert(value_type&& value) -> iterator
|
||||
requires(MaybeMulti && !MaybeMap);
|
||||
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
std::enable_if_t<!MaybeMulti, iterator>
|
||||
iterator
|
||||
insert(const_iterator /*hint*/, value_type const& value)
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
// Hint is ignored but we provide the interface so
|
||||
// callers may use ordered and unordered interchangeably.
|
||||
@@ -993,8 +991,9 @@ public:
|
||||
|
||||
// multimap, multiset
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
std::enable_if_t<MaybeMulti, iterator>
|
||||
iterator
|
||||
insert(const_iterator /*hint*/, value_type const& value)
|
||||
requires MaybeMulti
|
||||
{
|
||||
// VFALCO TODO The hint could be used to let
|
||||
// the client order equal ranges
|
||||
@@ -1003,8 +1002,9 @@ public:
|
||||
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
std::enable_if_t<!MaybeMulti, iterator>
|
||||
iterator
|
||||
insert(const_iterator /*hint*/, value_type&& value)
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
// Hint is ignored but we provide the interface so
|
||||
// callers may use ordered and unordered interchangeably.
|
||||
@@ -1013,8 +1013,9 @@ public:
|
||||
|
||||
// multimap, multiset
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
std::enable_if_t<MaybeMulti, iterator>
|
||||
iterator
|
||||
insert(const_iterator /*hint*/, value_type&& value)
|
||||
requires MaybeMulti
|
||||
{
|
||||
// VFALCO TODO The hint could be used to let
|
||||
// the client order equal ranges
|
||||
@@ -1023,20 +1024,18 @@ public:
|
||||
|
||||
// map, multimap
|
||||
template <class P, bool MaybeMap = IsMap>
|
||||
std::enable_if_t<
|
||||
MaybeMap && std::is_constructible_v<value_type, P&&>,
|
||||
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
|
||||
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
|
||||
insert(P&& value)
|
||||
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
|
||||
{
|
||||
return emplace(std::forward<P>(value));
|
||||
}
|
||||
|
||||
// map, multimap
|
||||
template <class P, bool MaybeMap = IsMap>
|
||||
std::enable_if_t<
|
||||
MaybeMap && std::is_constructible_v<value_type, P&&>,
|
||||
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>>
|
||||
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
|
||||
insert(const_iterator hint, P&& value)
|
||||
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
|
||||
{
|
||||
return emplaceHint(hint, std::forward<P>(value));
|
||||
}
|
||||
@@ -1057,23 +1056,26 @@ public:
|
||||
// set, map
|
||||
template <bool MaybeMulti = IsMulti, class... Args>
|
||||
auto
|
||||
emplace(Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
|
||||
emplace(Args&&... args) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multiset, multimap
|
||||
template <bool MaybeMulti = IsMulti, class... Args>
|
||||
auto
|
||||
emplace(Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>;
|
||||
emplace(Args&&... args) -> iterator
|
||||
requires MaybeMulti;
|
||||
|
||||
// set, map
|
||||
template <bool MaybeMulti = IsMulti, class... Args>
|
||||
auto
|
||||
emplaceHint(const_iterator /*hint*/, Args&&... args)
|
||||
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
|
||||
emplaceHint(const_iterator /*hint*/, Args&&... args) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multiset, multimap
|
||||
template <bool MaybeMulti = IsMulti, class... Args>
|
||||
std::enable_if_t<MaybeMulti, iterator>
|
||||
iterator
|
||||
emplaceHint(const_iterator /*hint*/, Args&&... args)
|
||||
requires MaybeMulti
|
||||
{
|
||||
// VFALCO TODO The hint could be used for multi, to let
|
||||
// the client order equal ranges
|
||||
@@ -1304,7 +1306,7 @@ public:
|
||||
class OtherHash,
|
||||
class OtherAllocator,
|
||||
bool MaybeMulti = IsMulti>
|
||||
std::enable_if_t<!MaybeMulti, bool>
|
||||
bool
|
||||
operator==(AgedUnorderedContainer<
|
||||
false,
|
||||
OtherIsMap,
|
||||
@@ -1313,7 +1315,8 @@ public:
|
||||
OtherDuration,
|
||||
OtherHash,
|
||||
KeyEqual,
|
||||
OtherAllocator> const& other) const;
|
||||
OtherAllocator> const& other) const
|
||||
requires(!MaybeMulti);
|
||||
|
||||
template <
|
||||
bool OtherIsMap,
|
||||
@@ -1323,7 +1326,7 @@ public:
|
||||
class OtherHash,
|
||||
class OtherAllocator,
|
||||
bool MaybeMulti = IsMulti>
|
||||
std::enable_if_t<MaybeMulti, bool>
|
||||
bool
|
||||
operator==(AgedUnorderedContainer<
|
||||
true,
|
||||
OtherIsMap,
|
||||
@@ -1332,7 +1335,8 @@ public:
|
||||
OtherDuration,
|
||||
OtherHash,
|
||||
KeyEqual,
|
||||
OtherAllocator> const& other) const;
|
||||
OtherAllocator> const& other) const
|
||||
requires MaybeMulti;
|
||||
|
||||
template <
|
||||
bool OtherIsMulti,
|
||||
@@ -1377,13 +1381,14 @@ private:
|
||||
// map, set
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
auto
|
||||
insertUnchecked(value_type const& value)
|
||||
-> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>;
|
||||
insertUnchecked(value_type const& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti);
|
||||
|
||||
// multimap, multiset
|
||||
template <bool MaybeMulti = IsMulti>
|
||||
auto
|
||||
insertUnchecked(value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>;
|
||||
insertUnchecked(value_type const& value) -> iterator
|
||||
requires MaybeMulti;
|
||||
|
||||
template <class InputIt>
|
||||
void
|
||||
@@ -1414,7 +1419,7 @@ private:
|
||||
void
|
||||
touch(
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
|
||||
typename clock_type::time_point const& now)
|
||||
clock_type::time_point const& now)
|
||||
{
|
||||
auto& e(*pos.iterator());
|
||||
e.when = now;
|
||||
@@ -1424,8 +1429,9 @@ private:
|
||||
|
||||
template <
|
||||
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
|
||||
std::enable_if_t<MaybePropagate>
|
||||
void
|
||||
swapData(AgedUnorderedContainer& other) noexcept
|
||||
requires MaybePropagate
|
||||
{
|
||||
std::swap(config_.hashFunction(), other.config_.hashFunction());
|
||||
std::swap(config_.keyEq(), other.config_.keyEq());
|
||||
@@ -1435,8 +1441,9 @@ private:
|
||||
|
||||
template <
|
||||
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
|
||||
std::enable_if_t<!MaybePropagate>
|
||||
void
|
||||
swapData(AgedUnorderedContainer& other) noexcept
|
||||
requires(!MaybePropagate)
|
||||
{
|
||||
std::swap(config_.hashFunction(), other.config_.hashFunction());
|
||||
std::swap(config_.keyEq(), other.config_.keyEq());
|
||||
@@ -2090,9 +2097,10 @@ template <
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Allocator>
|
||||
template <class K, bool MaybeMulti, bool MaybeMap, class>
|
||||
template <class K, bool MaybeMulti, bool MaybeMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::at(K const& k)
|
||||
requires(MaybeMap && !MaybeMulti)
|
||||
{
|
||||
auto const iter(
|
||||
cont_.find(k, std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual())));
|
||||
@@ -2110,10 +2118,11 @@ template <
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Allocator>
|
||||
template <class K, bool MaybeMulti, bool MaybeMap, class>
|
||||
typename std::conditional<IsMap, T, void*>::type const&
|
||||
template <class K, bool MaybeMulti, bool MaybeMap>
|
||||
std::conditional<IsMap, T, void*>::type const&
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::at(
|
||||
K const& k) const
|
||||
requires(MaybeMap && !MaybeMulti)
|
||||
{
|
||||
auto const iter(
|
||||
cont_.find(k, std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual())));
|
||||
@@ -2131,10 +2140,11 @@ template <
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Allocator>
|
||||
template <bool MaybeMulti, bool MaybeMap, class>
|
||||
template <bool MaybeMulti, bool MaybeMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator[](
|
||||
Key const& key)
|
||||
requires(MaybeMap && !MaybeMulti)
|
||||
{
|
||||
maybeRehash(1);
|
||||
typename cont_type::insert_commit_data d;
|
||||
@@ -2160,10 +2170,11 @@ template <
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Allocator>
|
||||
template <bool MaybeMulti, bool MaybeMap, class>
|
||||
template <bool MaybeMulti, bool MaybeMap>
|
||||
std::conditional_t<IsMap, T, void*>&
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator[](
|
||||
Key&& key)
|
||||
requires(MaybeMap && !MaybeMulti)
|
||||
{
|
||||
maybeRehash(1);
|
||||
typename cont_type::insert_commit_data d;
|
||||
@@ -2216,7 +2227,8 @@ template <
|
||||
template <bool MaybeMulti>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
|
||||
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
|
||||
value_type const& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
maybeRehash(1);
|
||||
typename cont_type::insert_commit_data d;
|
||||
@@ -2245,7 +2257,8 @@ template <
|
||||
template <bool MaybeMulti>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
|
||||
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
|
||||
value_type const& value) -> iterator
|
||||
requires MaybeMulti
|
||||
{
|
||||
maybeRehash(1);
|
||||
Element* const p(newElement(value));
|
||||
@@ -2267,7 +2280,8 @@ template <
|
||||
template <bool MaybeMulti, bool MaybeMap>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
|
||||
value_type&& value) -> std::enable_if_t<!MaybeMulti && !MaybeMap, std::pair<iterator, bool>>
|
||||
value_type&& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti && !MaybeMap)
|
||||
{
|
||||
maybeRehash(1);
|
||||
typename cont_type::insert_commit_data d;
|
||||
@@ -2296,7 +2310,8 @@ template <
|
||||
template <bool MaybeMulti, bool MaybeMap>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insert(
|
||||
value_type&& value) -> std::enable_if_t<MaybeMulti && !MaybeMap, iterator>
|
||||
value_type&& value) -> iterator
|
||||
requires(MaybeMulti && !MaybeMap)
|
||||
{
|
||||
maybeRehash(1);
|
||||
Element* const p(newElement(std::move(value)));
|
||||
@@ -2305,7 +2320,6 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
|
||||
return iterator(iter);
|
||||
}
|
||||
|
||||
#if 1 // Use insert() instead of insert_check() insert_commit()
|
||||
// set, map
|
||||
template <
|
||||
bool IsMulti,
|
||||
@@ -2319,7 +2333,8 @@ template <
|
||||
template <bool MaybeMulti, class... Args>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
|
||||
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
|
||||
Args&&... args) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
maybeRehash(1);
|
||||
// VFALCO NOTE Its unfortunate that we need to
|
||||
@@ -2334,42 +2349,6 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
|
||||
deleteElement(p);
|
||||
return std::make_pair(iterator(result.first), false);
|
||||
}
|
||||
#else // As original, use insert_check() / insert_commit () pair.
|
||||
// set, map
|
||||
template <
|
||||
bool IsMulti,
|
||||
bool IsMap,
|
||||
class Key,
|
||||
class T,
|
||||
class Clock,
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Allocator>
|
||||
template <bool maybe_multi, class... Args>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
|
||||
Args&&... args) -> typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type
|
||||
{
|
||||
maybe_rehash(1);
|
||||
// VFALCO NOTE Its unfortunate that we need to
|
||||
// construct element here
|
||||
element* const p(new_element(std::forward<Args>(args)...));
|
||||
typename cont_type::insert_commit_data d;
|
||||
auto const result(m_cont.insert_check(
|
||||
extract(p->value),
|
||||
std::cref(m_config.hashFunction()),
|
||||
std::cref(m_config.keyValueEqual()),
|
||||
d));
|
||||
if (result.second)
|
||||
{
|
||||
auto const iter(m_cont.insert_commit(*p, d));
|
||||
chronological.list.push_back(*p);
|
||||
return std::make_pair(iterator(iter), true);
|
||||
}
|
||||
delete_element(p);
|
||||
return std::make_pair(iterator(result.first), false);
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
// multiset, multimap
|
||||
template <
|
||||
@@ -2384,7 +2363,8 @@ template <
|
||||
template <bool MaybeMulti, class... Args>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplace(
|
||||
Args&&... args) -> std::enable_if_t<MaybeMulti, iterator>
|
||||
Args&&... args) -> iterator
|
||||
requires MaybeMulti
|
||||
{
|
||||
maybeRehash(1);
|
||||
Element* const p(newElement(std::forward<Args>(args)...));
|
||||
@@ -2407,7 +2387,8 @@ template <bool MaybeMulti, class... Args>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::emplaceHint(
|
||||
const_iterator /*hint*/,
|
||||
Args&&... args) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
|
||||
Args&&... args) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
maybeRehash(1);
|
||||
// VFALCO NOTE Its unfortunate that we need to
|
||||
@@ -2558,7 +2539,7 @@ template <
|
||||
class OtherHash,
|
||||
class OtherAllocator,
|
||||
bool MaybeMulti>
|
||||
std::enable_if_t<!MaybeMulti, bool>
|
||||
bool
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator==(
|
||||
AgedUnorderedContainer<
|
||||
false,
|
||||
@@ -2569,6 +2550,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
|
||||
OtherHash,
|
||||
KeyEqual,
|
||||
OtherAllocator> const& other) const
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
if (size() != other.size())
|
||||
return false;
|
||||
@@ -2598,7 +2580,7 @@ template <
|
||||
class OtherHash,
|
||||
class OtherAllocator,
|
||||
bool MaybeMulti>
|
||||
std::enable_if_t<MaybeMulti, bool>
|
||||
bool
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::operator==(
|
||||
AgedUnorderedContainer<
|
||||
true,
|
||||
@@ -2609,6 +2591,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
|
||||
OtherHash,
|
||||
KeyEqual,
|
||||
OtherAllocator> const& other) const
|
||||
requires MaybeMulti
|
||||
{
|
||||
if (size() != other.size())
|
||||
return false;
|
||||
@@ -2645,7 +2628,8 @@ template <
|
||||
template <bool MaybeMulti>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insertUnchecked(
|
||||
value_type const& value) -> std::enable_if_t<!MaybeMulti, std::pair<iterator, bool>>
|
||||
value_type const& value) -> std::pair<iterator, bool>
|
||||
requires(!MaybeMulti)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
auto const result(cont_.insert_check(
|
||||
@@ -2673,7 +2657,8 @@ template <
|
||||
template <bool MaybeMulti>
|
||||
auto
|
||||
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::insertUnchecked(
|
||||
value_type const& value) -> std::enable_if_t<MaybeMulti, iterator>
|
||||
value_type const& value) -> iterator
|
||||
requires MaybeMulti
|
||||
{
|
||||
Element* const p(newElement(value));
|
||||
chronological.list_.push_back(*p);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <boost/predef.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cctype>
|
||||
#include <charconv>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
@@ -28,16 +29,18 @@ struct LexicalCast<std::string, In>
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
template <class Arithmetic = In>
|
||||
std::enable_if_t<std::is_arithmetic_v<Arithmetic>, bool>
|
||||
bool
|
||||
operator()(std::string& out, Arithmetic in)
|
||||
requires(std::is_arithmetic_v<Arithmetic>)
|
||||
{
|
||||
out = std::to_string(in);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Enumeration = In>
|
||||
std::enable_if_t<std::is_enum_v<Enumeration>, bool>
|
||||
bool
|
||||
operator()(std::string& out, Enumeration in)
|
||||
requires(std::is_enum_v<Enumeration>)
|
||||
{
|
||||
out = std::to_string(static_cast<std::underlying_type_t<Enumeration>>(in));
|
||||
return true;
|
||||
@@ -55,8 +58,9 @@ struct LexicalCast<Out, std::string_view>
|
||||
"beast::LexicalCast can only be used with integral types");
|
||||
|
||||
template <class Integral = Out>
|
||||
std::enable_if_t<std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>, bool>
|
||||
bool
|
||||
operator()(Integral& out, std::string_view in) const
|
||||
requires(std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>)
|
||||
{
|
||||
auto first = in.data();
|
||||
auto last = in.data() + in.size();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -24,7 +26,7 @@ struct CopyConst<T const, U>
|
||||
{
|
||||
explicit CopyConst() = default;
|
||||
|
||||
using type = typename std::remove_const<U>::type const;
|
||||
using type = std::remove_const<U>::type const;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
@@ -56,7 +58,7 @@ class ListIterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = typename beast::detail::CopyConst<N, typename N::value_type>::type;
|
||||
using value_type = beast::detail::CopyConst<N, typename N::value_type>::type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
@@ -259,7 +261,7 @@ template <typename T, typename Tag = void>
|
||||
class List
|
||||
{
|
||||
public:
|
||||
using Node = typename detail::ListNode<T, Tag>;
|
||||
using Node = detail::ListNode<T, Tag>;
|
||||
|
||||
using value_type = T;
|
||||
using pointer = value_type*;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
@@ -12,13 +13,13 @@ template <class Container, bool IsConst>
|
||||
class LockFreeStackIterator
|
||||
{
|
||||
protected:
|
||||
using Node = typename Container::Node;
|
||||
using Node = Container::Node;
|
||||
using NodePtr = std::conditional_t<IsConst, Node const*, Node*>;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = typename Container::value_type;
|
||||
using difference_type = typename Container::difference_type;
|
||||
using value_type = Container::value_type;
|
||||
using difference_type = Container::difference_type;
|
||||
using pointer =
|
||||
std::conditional_t<IsConst, typename Container::const_pointer, typename Container::pointer>;
|
||||
using reference = std::
|
||||
@@ -40,7 +41,7 @@ public:
|
||||
operator=(NodePtr node)
|
||||
{
|
||||
node_ = node;
|
||||
return static_cast<LockFreeStackIterator&>(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LockFreeStackIterator&
|
||||
@@ -58,7 +59,7 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
NodePtr
|
||||
[[nodiscard]] NodePtr
|
||||
node() const
|
||||
{
|
||||
return node_;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
@@ -26,7 +26,7 @@ template <class T>
|
||||
inline void
|
||||
reverseBytes(T& t)
|
||||
{
|
||||
unsigned char* bytes =
|
||||
auto* bytes =
|
||||
static_cast<unsigned char*>(std::memmove(std::addressof(t), std::addressof(t), sizeof(T)));
|
||||
for (unsigned i = 0; i < sizeof(T) / 2; ++i)
|
||||
std::swap(bytes[i], bytes[sizeof(T) - 1 - i]);
|
||||
@@ -200,26 +200,29 @@ struct IsContiguouslyHashable<T[N], HashAlgorithm>
|
||||
// scalars
|
||||
|
||||
template <class Hasher, class T>
|
||||
inline std::enable_if_t<IsContiguouslyHashable<T, Hasher>::value>
|
||||
inline void
|
||||
hash_append(Hasher& h, T const& t) noexcept
|
||||
requires(IsContiguouslyHashable<T, Hasher>::value)
|
||||
{
|
||||
// NOLINTNEXTLINE(bugprone-sizeof-expression)
|
||||
h(static_cast<void const*>(std::addressof(t)), sizeof(t));
|
||||
}
|
||||
|
||||
template <class Hasher, class T>
|
||||
inline std::enable_if_t<
|
||||
!IsContiguouslyHashable<T, Hasher>::value &&
|
||||
(std::is_integral_v<T> || std::is_pointer_v<T> || std::is_enum_v<T>)>
|
||||
inline void
|
||||
hash_append(Hasher& h, T t) noexcept
|
||||
requires(
|
||||
!IsContiguouslyHashable<T, Hasher>::value &&
|
||||
(std::is_integral_v<T> || std::is_pointer_v<T> || std::is_enum_v<T>))
|
||||
{
|
||||
detail::reverseBytes(t);
|
||||
h(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
||||
template <class Hasher, class T>
|
||||
inline std::enable_if_t<std::is_floating_point_v<T>>
|
||||
inline void
|
||||
hash_append(Hasher& h, T t) noexcept
|
||||
requires(std::is_floating_point_v<T>)
|
||||
{
|
||||
if (t == 0)
|
||||
t = 0;
|
||||
@@ -239,36 +242,44 @@ hash_append(Hasher& h, std::nullptr_t) noexcept
|
||||
// Forward declarations for ADL purposes
|
||||
|
||||
template <class Hasher, class T, std::size_t N>
|
||||
std::enable_if_t<!IsContiguouslyHashable<T, Hasher>::value>
|
||||
hash_append(Hasher& h, T (&a)[N]) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, T (&a)[N]) noexcept
|
||||
requires(!IsContiguouslyHashable<T, Hasher>::value);
|
||||
|
||||
template <class Hasher, class CharT, class Traits, class Alloc>
|
||||
std::enable_if_t<!IsContiguouslyHashable<CharT, Hasher>::value>
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
|
||||
requires(!IsContiguouslyHashable<CharT, Hasher>::value);
|
||||
|
||||
template <class Hasher, class CharT, class Traits, class Alloc>
|
||||
std::enable_if_t<IsContiguouslyHashable<CharT, Hasher>::value>
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
|
||||
requires(IsContiguouslyHashable<CharT, Hasher>::value);
|
||||
|
||||
template <class Hasher, class T, class U>
|
||||
std::enable_if_t<!IsContiguouslyHashable<std::pair<T, U>, Hasher>::value>
|
||||
hash_append(Hasher& h, std::pair<T, U> const& p) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
|
||||
requires(!IsContiguouslyHashable<std::pair<T, U>, Hasher>::value);
|
||||
|
||||
template <class Hasher, class T, class Alloc>
|
||||
std::enable_if_t<!IsContiguouslyHashable<T, Hasher>::value>
|
||||
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
|
||||
requires(!IsContiguouslyHashable<T, Hasher>::value);
|
||||
|
||||
template <class Hasher, class T, class Alloc>
|
||||
std::enable_if_t<IsContiguouslyHashable<T, Hasher>::value>
|
||||
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
|
||||
requires(IsContiguouslyHashable<T, Hasher>::value);
|
||||
|
||||
template <class Hasher, class T, std::size_t N>
|
||||
std::enable_if_t<!IsContiguouslyHashable<std::array<T, N>, Hasher>::value>
|
||||
hash_append(Hasher& h, std::array<T, N> const& a) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, std::array<T, N> const& a) noexcept
|
||||
requires(!IsContiguouslyHashable<std::array<T, N>, Hasher>::value);
|
||||
|
||||
template <class Hasher, class... T>
|
||||
std::enable_if_t<!IsContiguouslyHashable<std::tuple<T...>, Hasher>::value>
|
||||
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
|
||||
requires(!IsContiguouslyHashable<std::tuple<T...>, Hasher>::value);
|
||||
|
||||
template <class Hasher, class Key, class T, class Hash, class Pred, class Alloc>
|
||||
void
|
||||
@@ -279,11 +290,13 @@ void
|
||||
hash_append(Hasher& h, std::unordered_set<Key, Hash, Pred, Alloc> const& s);
|
||||
|
||||
template <class Hasher, class Key, class Compare, class Alloc>
|
||||
std::enable_if_t<!IsContiguouslyHashable<Key, Hasher>::value>
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
requires(!IsContiguouslyHashable<Key, Hasher>::value);
|
||||
template <class Hasher, class Key, class Compare, class Alloc>
|
||||
std::enable_if_t<IsContiguouslyHashable<Key, Hasher>::value>
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
|
||||
void
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
requires(IsContiguouslyHashable<Key, Hasher>::value);
|
||||
template <class Hasher, class T0, class T1, class... T>
|
||||
void
|
||||
hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept;
|
||||
@@ -291,8 +304,9 @@ hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept;
|
||||
// c-array
|
||||
|
||||
template <class Hasher, class T, std::size_t N>
|
||||
std::enable_if_t<!IsContiguouslyHashable<T, Hasher>::value>
|
||||
void
|
||||
hash_append(Hasher& h, T (&a)[N]) noexcept
|
||||
requires(!IsContiguouslyHashable<T, Hasher>::value)
|
||||
{
|
||||
for (auto const& t : a)
|
||||
hash_append(h, t);
|
||||
@@ -301,8 +315,9 @@ hash_append(Hasher& h, T (&a)[N]) noexcept
|
||||
// basic_string
|
||||
|
||||
template <class Hasher, class CharT, class Traits, class Alloc>
|
||||
inline std::enable_if_t<!IsContiguouslyHashable<CharT, Hasher>::value>
|
||||
inline void
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
|
||||
requires(!IsContiguouslyHashable<CharT, Hasher>::value)
|
||||
{
|
||||
for (auto c : s)
|
||||
hash_append(h, c);
|
||||
@@ -310,8 +325,9 @@ hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcep
|
||||
}
|
||||
|
||||
template <class Hasher, class CharT, class Traits, class Alloc>
|
||||
inline std::enable_if_t<IsContiguouslyHashable<CharT, Hasher>::value>
|
||||
inline void
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
|
||||
requires(IsContiguouslyHashable<CharT, Hasher>::value)
|
||||
{
|
||||
h(s.data(), s.size() * sizeof(CharT));
|
||||
hash_append(h, s.size());
|
||||
@@ -320,8 +336,9 @@ hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcep
|
||||
// pair
|
||||
|
||||
template <class Hasher, class T, class U>
|
||||
inline std::enable_if_t<!IsContiguouslyHashable<std::pair<T, U>, Hasher>::value>
|
||||
inline void
|
||||
hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
|
||||
requires(!IsContiguouslyHashable<std::pair<T, U>, Hasher>::value)
|
||||
{
|
||||
hash_append(h, p.first, p.second);
|
||||
}
|
||||
@@ -329,8 +346,9 @@ hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
|
||||
// vector
|
||||
|
||||
template <class Hasher, class T, class Alloc>
|
||||
inline std::enable_if_t<!IsContiguouslyHashable<T, Hasher>::value>
|
||||
inline void
|
||||
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
|
||||
requires(!IsContiguouslyHashable<T, Hasher>::value)
|
||||
{
|
||||
for (auto const& t : v)
|
||||
hash_append(h, t);
|
||||
@@ -338,8 +356,9 @@ hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
|
||||
}
|
||||
|
||||
template <class Hasher, class T, class Alloc>
|
||||
inline std::enable_if_t<IsContiguouslyHashable<T, Hasher>::value>
|
||||
inline void
|
||||
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
|
||||
requires(IsContiguouslyHashable<T, Hasher>::value)
|
||||
{
|
||||
h(v.data(), v.size() * sizeof(T));
|
||||
hash_append(h, v.size());
|
||||
@@ -348,57 +367,37 @@ hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
|
||||
// array
|
||||
|
||||
template <class Hasher, class T, std::size_t N>
|
||||
std::enable_if_t<!IsContiguouslyHashable<std::array<T, N>, Hasher>::value>
|
||||
void
|
||||
hash_append(Hasher& h, std::array<T, N> const& a) noexcept
|
||||
requires(!IsContiguouslyHashable<std::array<T, N>, Hasher>::value)
|
||||
{
|
||||
for (auto const& t : a)
|
||||
hash_append(h, t);
|
||||
}
|
||||
|
||||
template <class Hasher, class Key, class Compare, class Alloc>
|
||||
std::enable_if_t<!IsContiguouslyHashable<Key, Hasher>::value>
|
||||
void
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
requires(!IsContiguouslyHashable<Key, Hasher>::value)
|
||||
{
|
||||
for (auto const& t : v)
|
||||
hash_append(h, t);
|
||||
}
|
||||
template <class Hasher, class Key, class Compare, class Alloc>
|
||||
std::enable_if_t<IsContiguouslyHashable<Key, Hasher>::value>
|
||||
void
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
requires(IsContiguouslyHashable<Key, Hasher>::value)
|
||||
{
|
||||
h(&(v.begin()), v.size() * sizeof(Key));
|
||||
}
|
||||
// tuple
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline void
|
||||
forEachItem(...) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template <class Hasher, class T>
|
||||
inline int
|
||||
hashOne(Hasher& h, T const& t) noexcept
|
||||
{
|
||||
hash_append(h, t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Hasher, class... T, std::size_t... I>
|
||||
inline void
|
||||
tuple_hash(Hasher& h, std::tuple<T...> const& t, std::index_sequence<I...>) noexcept
|
||||
{
|
||||
for_each_item(hash_one(h, std::get<I>(t))...);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Hasher, class... T>
|
||||
inline std::enable_if_t<!IsContiguouslyHashable<std::tuple<T...>, Hasher>::value>
|
||||
inline void
|
||||
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
|
||||
requires(!IsContiguouslyHashable<std::tuple<T...>, Hasher>::value)
|
||||
{
|
||||
detail::tuple_hash(h, t, std::index_sequence_for<T...>{});
|
||||
std::apply([&h](auto const&... item) { (hash_append(h, item), ...); }, t);
|
||||
}
|
||||
|
||||
// shared_ptr
|
||||
|
||||
@@ -11,7 +11,7 @@ struct Uhash
|
||||
{
|
||||
Uhash() = default;
|
||||
|
||||
using result_type = typename Hasher::result_type;
|
||||
using result_type = Hasher::result_type;
|
||||
|
||||
template <class T>
|
||||
result_type
|
||||
|
||||
@@ -7,8 +7,11 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -121,14 +124,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <class Seed, std::enable_if_t<std::is_unsigned_v<Seed>>* = nullptr>
|
||||
explicit Xxhasher(Seed seed) : seed_(seed)
|
||||
template <class Seed>
|
||||
explicit Xxhasher(Seed seed)
|
||||
requires(std::is_unsigned_v<Seed>)
|
||||
: seed_(seed)
|
||||
{
|
||||
resetBuffers();
|
||||
}
|
||||
|
||||
template <class Seed, std::enable_if_t<std::is_unsigned_v<Seed>>* = nullptr>
|
||||
Xxhasher(Seed seed, Seed) : seed_(seed)
|
||||
template <class Seed>
|
||||
Xxhasher(Seed seed, Seed)
|
||||
requires(std::is_unsigned_v<Seed>)
|
||||
: seed_(seed)
|
||||
{
|
||||
resetBuffers();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
#include <xrpl/beast/insight/Event.h>
|
||||
#include <xrpl/beast/insight/Gauge.h>
|
||||
#include <xrpl/beast/insight/Hook.h>
|
||||
#include <xrpl/beast/insight/HookImpl.h>
|
||||
#include <xrpl/beast/insight/Meter.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace beast::insight {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/insight/CounterImpl.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast::insight {
|
||||
|
||||
@@ -29,7 +30,7 @@ public:
|
||||
factory function in the Collector interface.
|
||||
@see Collector.
|
||||
*/
|
||||
explicit Counter(std::shared_ptr<CounterImpl> const& impl) : impl_(impl)
|
||||
explicit Counter(std::shared_ptr<CounterImpl> impl) : impl_(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast::insight {
|
||||
|
||||
@@ -31,7 +32,7 @@ public:
|
||||
factory function in the Collector interface.
|
||||
@see Collector.
|
||||
*/
|
||||
explicit Event(std::shared_ptr<EventImpl> const& impl) : impl_(impl)
|
||||
explicit Event(std::shared_ptr<EventImpl> impl) : impl_(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/insight/GaugeImpl.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast::insight {
|
||||
|
||||
@@ -31,7 +32,7 @@ public:
|
||||
factory function in the Collector interface.
|
||||
@see Collector.
|
||||
*/
|
||||
explicit Gauge(std::shared_ptr<GaugeImpl> const& impl) : impl_(impl)
|
||||
explicit Gauge(std::shared_ptr<GaugeImpl> impl) : impl_(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -48,6 +49,11 @@ public:
|
||||
impl_->set(value);
|
||||
}
|
||||
|
||||
// This is a write-through handle: assignment sets the value of the
|
||||
// referenced metric. It is const-qualified and returns Gauge const&
|
||||
// (a non-const Gauge& would require a const_cast), so it does not follow
|
||||
// the conventional assignment-operator signature.
|
||||
// NOLINTNEXTLINE(misc-unconventional-assign-operator)
|
||||
Gauge const&
|
||||
operator=(value_type value) const
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/insight/HookImpl.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast::insight {
|
||||
|
||||
@@ -20,7 +21,7 @@ public:
|
||||
factory function in the Collector interface.
|
||||
@see Collector.
|
||||
*/
|
||||
explicit Hook(std::shared_ptr<HookImpl> const& impl) : impl_(impl)
|
||||
explicit Hook(std::shared_ptr<HookImpl> impl) : impl_(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/insight/Collector.h>
|
||||
#include <xrpl/beast/insight/Counter.h>
|
||||
#include <xrpl/beast/insight/CounterImpl.h>
|
||||
#include <xrpl/beast/insight/Event.h>
|
||||
#include <xrpl/beast/insight/EventImpl.h>
|
||||
#include <xrpl/beast/insight/Gauge.h>
|
||||
#include <xrpl/beast/insight/GaugeImpl.h>
|
||||
#include <xrpl/beast/insight/Group.h>
|
||||
#include <xrpl/beast/insight/Groups.h>
|
||||
#include <xrpl/beast/insight/Hook.h>
|
||||
#include <xrpl/beast/insight/HookImpl.h>
|
||||
#include <xrpl/beast/insight/NullCollector.h>
|
||||
#include <xrpl/beast/insight/StatsDCollector.h>
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/insight/MeterImpl.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast::insight {
|
||||
|
||||
@@ -28,7 +29,7 @@ public:
|
||||
factory function in the Collector interface.
|
||||
@see Collector.
|
||||
*/
|
||||
explicit Meter(std::shared_ptr<MeterImpl> const& impl) : impl_(impl)
|
||||
explicit Meter(std::shared_ptr<MeterImpl> impl) : impl_(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <xrpl/beast/insight/Collector.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace beast::insight {
|
||||
|
||||
/** A Collector which does not collect metrics. */
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace beast::insight {
|
||||
|
||||
/** A Collector that reports metrics to a StatsD server.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/hash/hash_append.h>
|
||||
|
||||
#include <boost/asio/ip/address_v4.hpp>
|
||||
|
||||
namespace beast::IP {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <boost/asio/ip/address_v6.hpp>
|
||||
|
||||
namespace beast::IP {
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
#include <xrpl/beast/hash/hash_append.h>
|
||||
#include <xrpl/beast/hash/uhash.h>
|
||||
#include <xrpl/beast/net/IPAddress.h>
|
||||
#include <xrpl/beast/net/IPAddressV4.h>
|
||||
#include <xrpl/beast/net/IPAddressV6.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <istream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -102,7 +103,7 @@ Result
|
||||
split(FwdIt first, FwdIt last, Char delim)
|
||||
{
|
||||
using namespace detail;
|
||||
using string = typename Result::value_type;
|
||||
using string = Result::value_type;
|
||||
|
||||
Result result;
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <boost/thread/csbl/memory/allocator_arg.hpp>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@@ -23,6 +23,7 @@ typeName()
|
||||
if (auto s = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, nullptr))
|
||||
{
|
||||
name = s;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
|
||||
std::free(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/unit_test/amount.h>
|
||||
#include <xrpl/beast/unit_test/global_suites.h>
|
||||
#include <xrpl/beast/unit_test/match.h>
|
||||
#include <xrpl/beast/unit_test/recorder.h>
|
||||
#include <xrpl/beast/unit_test/reporter.h>
|
||||
#include <xrpl/beast/unit_test/results.h>
|
||||
#include <xrpl/beast/unit_test/runner.h>
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/beast/unit_test/suite_info.h>
|
||||
#include <xrpl/beast/unit_test/suite_list.h>
|
||||
|
||||
#ifndef BEAST_EXPECT
|
||||
#define BEAST_EXPECT_S1(x) #x
|
||||
|
||||
@@ -32,11 +32,11 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = typename cont_type::value_type;
|
||||
using size_type = typename cont_type::size_type;
|
||||
using difference_type = typename cont_type::difference_type;
|
||||
using iterator = typename cont_type::const_iterator;
|
||||
using const_iterator = typename cont_type::const_iterator;
|
||||
using value_type = cont_type::value_type;
|
||||
using size_type = cont_type::size_type;
|
||||
using difference_type = cont_type::difference_type;
|
||||
using iterator = cont_type::const_iterator;
|
||||
using const_iterator = cont_type::const_iterator;
|
||||
|
||||
/** Returns `true` if the container is empty. */
|
||||
[[nodiscard]] bool
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/beast/unit_test/suite_info.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast::unit_test {
|
||||
|
||||
@@ -41,7 +42,7 @@ private:
|
||||
|
||||
public:
|
||||
template <class = void>
|
||||
explicit Selector(ModeT mode, std::string const& pattern = "");
|
||||
explicit Selector(ModeT mode, std::string pattern = "");
|
||||
|
||||
template <class = void>
|
||||
bool
|
||||
@@ -51,9 +52,9 @@ public:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
Selector::Selector(ModeT mode, std::string const& pattern) : mode_(mode), pat_(pattern)
|
||||
Selector::Selector(ModeT mode, std::string pattern) : mode_(mode), pat_(std::move(pattern))
|
||||
{
|
||||
if (mode_ == ModeT::Automatch && pattern.empty())
|
||||
if (mode_ == ModeT::Automatch && pat_.empty())
|
||||
mode_ = ModeT::All;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
#include <xrpl/beast/unit_test/results.h>
|
||||
#include <xrpl/beast/unit_test/runner.h>
|
||||
#include <xrpl/beast/unit_test/suite_info.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast::unit_test {
|
||||
|
||||
|
||||
@@ -5,18 +5,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/unit_test/amount.h>
|
||||
#include <xrpl/beast/unit_test/recorder.h>
|
||||
#include <xrpl/beast/unit_test/runner.h>
|
||||
#include <xrpl/beast/unit_test/suite_info.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace beast::unit_test {
|
||||
|
||||
@@ -48,7 +51,7 @@ private:
|
||||
std::size_t cases = 0;
|
||||
std::size_t total = 0;
|
||||
std::size_t failed = 0;
|
||||
typename clock_type::time_point start = clock_type::now();
|
||||
clock_type::time_point start = clock_type::now();
|
||||
|
||||
explicit SuiteResults(std::string name = "") : name(std::move(name))
|
||||
{
|
||||
@@ -60,7 +63,7 @@ private:
|
||||
|
||||
struct Results
|
||||
{
|
||||
using run_time = std::pair<std::string, typename clock_type::duration>;
|
||||
using run_time = std::pair<std::string, clock_type::duration>;
|
||||
|
||||
static constexpr auto kMaxTop = 10;
|
||||
|
||||
@@ -69,7 +72,7 @@ private:
|
||||
std::size_t total = 0;
|
||||
std::size_t failed = 0;
|
||||
std::vector<run_time> top;
|
||||
typename clock_type::time_point start = clock_type::now();
|
||||
clock_type::time_point start = clock_type::now();
|
||||
|
||||
void
|
||||
add(SuiteResults const& r);
|
||||
@@ -77,8 +80,8 @@ private:
|
||||
|
||||
std::ostream& os_;
|
||||
Results results_;
|
||||
SuiteResults suite_results_;
|
||||
CaseResults case_results_;
|
||||
SuiteResults suiteResults_;
|
||||
CaseResults caseResults_;
|
||||
|
||||
public:
|
||||
Reporter(Reporter const&) = delete;
|
||||
@@ -91,7 +94,7 @@ public:
|
||||
|
||||
private:
|
||||
static std::string
|
||||
fmtdur(typename clock_type::duration const& d);
|
||||
fmtdur(clock_type::duration const& d);
|
||||
|
||||
void
|
||||
onSuiteBegin(SuiteInfo const& info) override;
|
||||
@@ -141,9 +144,7 @@ Reporter<Unused>::Results::add(SuiteResults const& r)
|
||||
top.begin(),
|
||||
top.end(),
|
||||
elapsed,
|
||||
[](run_time const& t1, typename clock_type::duration const& t2) {
|
||||
return t1.second > t2;
|
||||
});
|
||||
[](run_time const& t1, clock_type::duration const& t2) { return t1.second > t2; });
|
||||
if (iter != top.end())
|
||||
{
|
||||
if (top.size() == kMaxTop)
|
||||
@@ -181,7 +182,7 @@ Reporter<Unused>::~Reporter()
|
||||
|
||||
template <class Unused>
|
||||
std::string
|
||||
Reporter<Unused>::fmtdur(typename clock_type::duration const& d)
|
||||
Reporter<Unused>::fmtdur(clock_type::duration const& d)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto const ms = duration_cast<milliseconds>(d);
|
||||
@@ -196,22 +197,22 @@ template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onSuiteBegin(SuiteInfo const& info)
|
||||
{
|
||||
suite_results_ = SuiteResults{info.fullName()};
|
||||
suiteResults_ = SuiteResults{info.fullName()};
|
||||
}
|
||||
|
||||
template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onSuiteEnd()
|
||||
{
|
||||
results_.add(suite_results_);
|
||||
results_.add(suiteResults_);
|
||||
}
|
||||
|
||||
template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onCaseBegin(std::string const& name)
|
||||
{
|
||||
case_results_ = CaseResults(name);
|
||||
os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name))
|
||||
caseResults_ = CaseResults(name);
|
||||
os_ << suiteResults_.name << (caseResults_.name.empty() ? "" : (" " + caseResults_.name))
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
@@ -219,23 +220,23 @@ template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onCaseEnd()
|
||||
{
|
||||
suite_results_.add(case_results_);
|
||||
suiteResults_.add(caseResults_);
|
||||
}
|
||||
|
||||
template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onPass()
|
||||
{
|
||||
++case_results_.total;
|
||||
++caseResults_.total;
|
||||
}
|
||||
|
||||
template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onFail(std::string const& reason)
|
||||
{
|
||||
++case_results_.failed;
|
||||
++case_results_.total;
|
||||
os_ << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason
|
||||
++caseResults_.failed;
|
||||
++caseResults_.total;
|
||||
os_ << "#" << caseResults_.total << " failed" << (reason.empty() ? "" : ": ") << reason
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <xrpl/beast/unit_test/detail/const_container.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@@ -634,7 +636,7 @@ Suite::run(Runner& r)
|
||||
#define BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Class, Module, Library, Priority)
|
||||
|
||||
#else
|
||||
#include <xrpl/beast/unit_test/global_suites.h>
|
||||
#include <xrpl/beast/unit_test/global_suites.h> // IWYU pragma: keep
|
||||
#define BEAST_DEFINE_TESTSUITE(Class, Module, Library) \
|
||||
BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, false, 0)
|
||||
#define BEAST_DEFINE_TESTSUITE_MANUAL(Class, Module, Library) \
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace beast::unit_test {
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <typeindex>
|
||||
#include <unordered_set>
|
||||
#include <string> // IWYU pragma: keep
|
||||
#include <typeindex> // IWYU pragma: keep
|
||||
#include <unordered_set> // IWYU pragma: keep
|
||||
|
||||
namespace beast::unit_test {
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
@@ -43,7 +45,10 @@ public:
|
||||
template <class F, class... Args>
|
||||
explicit Thread(Suite& s, F&& f, Args&&... args) : s_(&s)
|
||||
{
|
||||
std::function<void(void)> b = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
std::function<void(void)> b = [f = std::forward<F>(f),
|
||||
... args = std::forward<Args>(args)]() mutable {
|
||||
std::invoke(f, args...);
|
||||
};
|
||||
t_ = std::thread(&Thread::run, this, std::move(b));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -105,12 +108,12 @@ public:
|
||||
};
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
static_assert(!std::is_default_constructible_v<Sink>, "");
|
||||
static_assert(!std::is_copy_constructible_v<Sink>, "");
|
||||
static_assert(!std::is_move_constructible_v<Sink>, "");
|
||||
static_assert(!std::is_copy_assignable_v<Sink>, "");
|
||||
static_assert(!std::is_move_assignable_v<Sink>, "");
|
||||
static_assert(std::is_nothrow_destructible_v<Sink>, "");
|
||||
static_assert(!std::is_default_constructible_v<Sink>);
|
||||
static_assert(!std::is_copy_constructible_v<Sink>);
|
||||
static_assert(!std::is_move_constructible_v<Sink>);
|
||||
static_assert(!std::is_copy_assignable_v<Sink>);
|
||||
static_assert(!std::is_move_assignable_v<Sink>);
|
||||
static_assert(std::is_nothrow_destructible_v<Sink>);
|
||||
#endif
|
||||
|
||||
/** Returns a Sink which does nothing. */
|
||||
@@ -161,12 +164,12 @@ public:
|
||||
};
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
static_assert(!std::is_default_constructible_v<ScopedStream>, "");
|
||||
static_assert(std::is_copy_constructible_v<ScopedStream>, "");
|
||||
static_assert(std::is_move_constructible_v<ScopedStream>, "");
|
||||
static_assert(!std::is_copy_assignable_v<ScopedStream>, "");
|
||||
static_assert(!std::is_move_assignable_v<ScopedStream>, "");
|
||||
static_assert(std::is_nothrow_destructible_v<ScopedStream>, "");
|
||||
static_assert(!std::is_default_constructible_v<ScopedStream>);
|
||||
static_assert(std::is_copy_constructible_v<ScopedStream>);
|
||||
static_assert(std::is_move_constructible_v<ScopedStream>);
|
||||
static_assert(!std::is_copy_assignable_v<ScopedStream>);
|
||||
static_assert(!std::is_move_assignable_v<ScopedStream>);
|
||||
static_assert(std::is_nothrow_destructible_v<ScopedStream>);
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -243,12 +246,12 @@ public:
|
||||
};
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
static_assert(std::is_default_constructible_v<Stream>, "");
|
||||
static_assert(std::is_copy_constructible_v<Stream>, "");
|
||||
static_assert(std::is_move_constructible_v<Stream>, "");
|
||||
static_assert(!std::is_copy_assignable_v<Stream>, "");
|
||||
static_assert(!std::is_move_assignable_v<Stream>, "");
|
||||
static_assert(std::is_nothrow_destructible_v<Stream>, "");
|
||||
static_assert(std::is_default_constructible_v<Stream>);
|
||||
static_assert(std::is_copy_constructible_v<Stream>);
|
||||
static_assert(std::is_move_constructible_v<Stream>);
|
||||
static_assert(!std::is_copy_assignable_v<Stream>);
|
||||
static_assert(!std::is_move_assignable_v<Stream>);
|
||||
static_assert(std::is_nothrow_destructible_v<Stream>);
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -326,12 +329,12 @@ public:
|
||||
};
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
static_assert(!std::is_default_constructible_v<Journal>, "");
|
||||
static_assert(std::is_copy_constructible_v<Journal>, "");
|
||||
static_assert(std::is_move_constructible_v<Journal>, "");
|
||||
static_assert(std::is_copy_assignable_v<Journal>, "");
|
||||
static_assert(std::is_move_assignable_v<Journal>, "");
|
||||
static_assert(std::is_nothrow_destructible_v<Journal>, "");
|
||||
static_assert(!std::is_default_constructible_v<Journal>);
|
||||
static_assert(std::is_copy_constructible_v<Journal>);
|
||||
static_assert(std::is_move_constructible_v<Journal>);
|
||||
static_assert(std::is_copy_assignable_v<Journal>);
|
||||
static_assert(std::is_move_assignable_v<Journal>);
|
||||
static_assert(std::is_nothrow_destructible_v<Journal>);
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -411,9 +414,9 @@ class BasicLogstream : public std::basic_ostream<CharT, Traits>
|
||||
{
|
||||
using char_type = CharT;
|
||||
using traits_type = Traits;
|
||||
using int_type = typename traits_type::int_type;
|
||||
using pos_type = typename traits_type::pos_type;
|
||||
using off_type = typename traits_type::off_type;
|
||||
using int_type = traits_type::int_type;
|
||||
using pos_type = traits_type::pos_type;
|
||||
using off_type = traits_type::off_type;
|
||||
|
||||
detail::LogStreamBuf<CharT, Traits> buf_;
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
#include <xrpl/beast/core/List.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -26,9 +26,7 @@ struct Zero
|
||||
explicit Zero() = default;
|
||||
};
|
||||
|
||||
namespace {
|
||||
constexpr Zero kZero{};
|
||||
} // namespace
|
||||
inline constexpr Zero kZero{};
|
||||
|
||||
/** Default implementation of signum calls the method on the class. */
|
||||
template <typename T>
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
// Macros below are copied from antithesis_sdk.h and slightly simplified
|
||||
// The duplication is because Visual Studio 2019 cannot compile that header
|
||||
// even with the option -Zc:__cplusplus added.
|
||||
// NOTE: cond must not contain bare commas outside () or []. Commas inside {}
|
||||
// are not protected by the preprocessor and would be parsed as extra arguments.
|
||||
#define ALWAYS(cond, message, ...) assert((message) && (cond))
|
||||
#define ALWAYS_OR_UNREACHABLE(cond, message) assert((message) && (cond))
|
||||
#define SOMETIMES(cond, message, ...)
|
||||
@@ -22,6 +24,8 @@
|
||||
#define XRPL_ASSERT_PARTS(cond, function, description, ...) \
|
||||
XRPL_ASSERT(cond, function " : " description)
|
||||
|
||||
#define XRPL_ASSERT_IF(guard, cond, message) XRPL_ASSERT(!(guard) || (cond), message)
|
||||
|
||||
// How to use the instrumentation macros:
|
||||
//
|
||||
// * XRPL_ASSERT if cond must be true but the line might not be reached during
|
||||
@@ -29,6 +33,14 @@
|
||||
// * XRPL_ASSERT_PARTS is for convenience, and works like XRPL_ASSERT, but
|
||||
// splits the message param into "function" and "description", then joins
|
||||
// them with " : " before passing to XRPL_ASSERT.
|
||||
// * XRPL_ASSERT_IF(guard, cond, message) asserts the implication
|
||||
// `guard => cond`: it can only fail when guard is true (e.g. an amendment
|
||||
// is enabled) and cond is false. Unlike `if (guard) XRPL_ASSERT(...)`, the
|
||||
// assertion site is always evaluated, so the fuzzer registers it
|
||||
// unconditionally; cond itself is short-circuited and only evaluated when
|
||||
// guard is true. NOTE: do not rely on side effects in guard — in release
|
||||
// builds the assertion body is stripped, and the compiler may optimize away
|
||||
// a side-effect-free guard entirely.
|
||||
// * ALWAYS if cond must be true _and_ the line must be reached during fuzzing.
|
||||
// Same like `assert` in normal use.
|
||||
// * REACHABLE if the line must be reached during fuzzing
|
||||
|
||||
@@ -15,6 +15,6 @@ struct MaybeConst
|
||||
|
||||
/** Alias for omitting `typename`. */
|
||||
template <bool IsConst, class T>
|
||||
using maybe_const_t = typename MaybeConst<IsConst, T>::type;
|
||||
using maybe_const_t = MaybeConst<IsConst, T>::type;
|
||||
|
||||
} // namespace beast
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -13,10 +10,10 @@ template <class Generator>
|
||||
void
|
||||
rngfill(void* const buffer, std::size_t const bytes, Generator& g)
|
||||
{
|
||||
using result_type = typename Generator::result_type;
|
||||
using result_type = Generator::result_type;
|
||||
constexpr std::size_t kResultSize = sizeof(result_type);
|
||||
|
||||
std::uint8_t* const bufferStart = static_cast<std::uint8_t*>(buffer);
|
||||
auto* const bufferStart = static_cast<std::uint8_t*>(buffer);
|
||||
std::size_t const completeIterations = bytes / kResultSize;
|
||||
std::size_t const bytesRemaining = bytes % kResultSize;
|
||||
|
||||
@@ -35,16 +32,14 @@ rngfill(void* const buffer, std::size_t const bytes, Generator& g)
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
class Generator,
|
||||
std::size_t N,
|
||||
class = std::enable_if_t<N % sizeof(typename Generator::result_type) == 0>>
|
||||
template <class Generator, std::size_t N>
|
||||
void
|
||||
rngfill(std::array<std::uint8_t, N>& a, Generator& g)
|
||||
requires(N % sizeof(typename Generator::result_type) == 0)
|
||||
{
|
||||
using result_type = typename Generator::result_type;
|
||||
using result_type = Generator::result_type;
|
||||
auto i = N / sizeof(result_type);
|
||||
result_type* p = reinterpret_cast<result_type*>(a.data());
|
||||
auto* p = reinterpret_cast<result_type*>(a.data());
|
||||
while (i--)
|
||||
*p++ = g();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,12 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/conditions/detail/utils.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <system_error>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::cryptoconditions {
|
||||
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/conditions/Condition.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
|
||||
namespace xrpl::cryptoconditions {
|
||||
|
||||
struct Fulfillment
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
#include <xrpl/conditions/detail/error.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::cryptoconditions {
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <system_error>
|
||||
|
||||
// A collection of functions to decode binary blobs
|
||||
// encoded with X.690 Distinguished Encoding Rules.
|
||||
|
||||
@@ -6,9 +6,13 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
@@ -298,7 +302,8 @@ set(T& target, std::string const& name, Section const& section)
|
||||
try
|
||||
{
|
||||
auto const val = section.get<T>(name);
|
||||
if ((foundAndValid = val.has_value()))
|
||||
foundAndValid = val.has_value();
|
||||
if (foundAndValid)
|
||||
target = *val;
|
||||
}
|
||||
catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
|
||||
180
include/xrpl/config/Constants.h
Normal file
180
include/xrpl/config/Constants.h
Normal file
@@ -0,0 +1,180 @@
|
||||
#pragma once
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
struct Sections
|
||||
{
|
||||
static constexpr auto kAmendments = "amendments";
|
||||
static constexpr auto kAmendmentMajorityTime = "amendment_majority_time";
|
||||
static constexpr auto kBetaRpcApi = "beta_rpc_api";
|
||||
static constexpr auto kClusterNodes = "cluster_nodes";
|
||||
static constexpr auto kCompression = "compression";
|
||||
static constexpr auto kCrawl = "crawl";
|
||||
static constexpr auto kDatabasePath = "database_path";
|
||||
static constexpr auto kDebugLogfile = "debug_logfile";
|
||||
static constexpr auto kElbSupport = "elb_support";
|
||||
static constexpr auto kFeatures = "features";
|
||||
static constexpr auto kFeeDefault = "fee_default";
|
||||
static constexpr auto kFetchDepth = "fetch_depth";
|
||||
static constexpr auto kHashrouter = "hashrouter";
|
||||
static constexpr auto kImportNodeDatabase = "import_db";
|
||||
static constexpr auto kInsight = "insight";
|
||||
static constexpr auto kIoWorkers = "io_workers";
|
||||
static constexpr auto kIps = "ips";
|
||||
static constexpr auto kIpsFixed = "ips_fixed";
|
||||
static constexpr auto kLedgerHistory = "ledger_history";
|
||||
static constexpr auto kLedgerReplay = "ledger_replay";
|
||||
static constexpr auto kLedgerTxTables = "ledger_tx_tables";
|
||||
static constexpr auto kMaxTransactions = "max_transactions";
|
||||
static constexpr auto kNetworkId = "network_id";
|
||||
static constexpr auto kNetworkQuorum = "network_quorum";
|
||||
static constexpr auto kNodeDatabase = "node_db";
|
||||
static constexpr auto kNodeSeed = "node_seed";
|
||||
static constexpr auto kNodeSize = "node_size";
|
||||
static constexpr auto kOverlay = "overlay";
|
||||
static constexpr auto kPathSearch = "path_search";
|
||||
static constexpr auto kPathSearchFast = "path_search_fast";
|
||||
static constexpr auto kPathSearchMax = "path_search_max";
|
||||
static constexpr auto kPathSearchOld = "path_search_old";
|
||||
static constexpr auto kPeerPrivate = "peer_private";
|
||||
static constexpr auto kPeersInMax = "peers_in_max";
|
||||
static constexpr auto kPeersMax = "peers_max";
|
||||
static constexpr auto kPeersOutMax = "peers_out_max";
|
||||
static constexpr auto kPerf = "perf";
|
||||
static constexpr auto kPortGrpc = "port_grpc";
|
||||
static constexpr auto kPortPeer = "port_peer";
|
||||
static constexpr auto kPortRpc = "port_rpc";
|
||||
static constexpr auto kPortWs = "port_ws";
|
||||
static constexpr auto kPortWssAdmin = "port_wss_admin";
|
||||
static constexpr auto kPrefetchWorkers = "prefetch_workers";
|
||||
static constexpr auto kReduceRelay = "reduce_relay";
|
||||
static constexpr auto kRelationalDb = "relational_db";
|
||||
static constexpr auto kRelayProposals = "relay_proposals";
|
||||
static constexpr auto kRelayValidations = "relay_validations";
|
||||
static constexpr auto kRpcStartup = "rpc_startup";
|
||||
static constexpr auto kServer = "server";
|
||||
static constexpr auto kServerDomain = "server_domain";
|
||||
static constexpr auto kSigningSupport = "signing_support";
|
||||
static constexpr auto kSntp = "sntp_servers";
|
||||
static constexpr auto kSqdb = "sqdb";
|
||||
static constexpr auto kSqlite = "sqlite";
|
||||
static constexpr auto kSslVerify = "ssl_verify";
|
||||
static constexpr auto kSslVerifyDir = "ssl_verify_dir";
|
||||
static constexpr auto kSslVerifyFile = "ssl_verify_file";
|
||||
static constexpr auto kSweepInterval = "sweep_interval";
|
||||
static constexpr auto kTransactionQueue = "transaction_queue";
|
||||
static constexpr auto kValidationSeed = "validation_seed";
|
||||
static constexpr auto kValidatorKeys = "validator_keys";
|
||||
static constexpr auto kValidatorKeyRevocation = "validator_key_revocation";
|
||||
static constexpr auto kValidatorListKeys = "validator_list_keys";
|
||||
static constexpr auto kValidatorListSites = "validator_list_sites";
|
||||
static constexpr auto kValidatorListThreshold = "validator_list_threshold";
|
||||
static constexpr auto kValidatorToken = "validator_token";
|
||||
static constexpr auto kValidators = "validators";
|
||||
static constexpr auto kValidatorsFile = "validators_file";
|
||||
static constexpr auto kVetoAmendments = "veto_amendments";
|
||||
static constexpr auto kVl = "vl";
|
||||
static constexpr auto kVoting = "voting";
|
||||
static constexpr auto kWorkers = "workers";
|
||||
};
|
||||
|
||||
struct Keys
|
||||
{
|
||||
static constexpr auto kAccountReserve = "account_reserve";
|
||||
static constexpr auto kAddress = "address";
|
||||
static constexpr auto kAdmin = "admin";
|
||||
static constexpr auto kAdminPassword = "admin_password";
|
||||
static constexpr auto kAdminUser = "admin_user";
|
||||
static constexpr auto kAdvisoryDelete = "advisory_delete";
|
||||
static constexpr auto kAgeThresholdSeconds = "age_threshold_seconds";
|
||||
static constexpr auto kBackOff = "backOff";
|
||||
static constexpr auto kBackOffMilliseconds = "back_off_milliseconds";
|
||||
static constexpr auto kBackend = "backend";
|
||||
static constexpr auto kBbtOptions = "bbt_options";
|
||||
static constexpr auto kBgThreads = "bg_threads";
|
||||
static constexpr auto kBlockSize = "block_size";
|
||||
static constexpr auto kCacheAge = "cache_age";
|
||||
static constexpr auto kCacheMb = "cache_mb";
|
||||
static constexpr auto kCacheSize = "cache_size";
|
||||
static constexpr auto kClientMaxWindowBits = "client_max_window_bits";
|
||||
static constexpr auto kClientNoContextTakeover = "client_no_context_takeover";
|
||||
static constexpr auto kCompressLevel = "compress_level";
|
||||
static constexpr auto kCounts = "counts";
|
||||
static constexpr auto kDeleteBatch = "delete_batch";
|
||||
static constexpr auto kEarliestSeq = "earliest_seq";
|
||||
static constexpr auto kFastLoad = "fast_load";
|
||||
static constexpr auto kFileSizeMb = "file_size_mb";
|
||||
static constexpr auto kFileSizeMult = "file_size_mult";
|
||||
static constexpr auto kFilterBits = "filter_bits";
|
||||
static constexpr auto kFilterFull = "filter_full";
|
||||
static constexpr auto kHardSet = "hard_set";
|
||||
static constexpr auto kHighThreads = "high_threads";
|
||||
static constexpr auto kHoldTime = "hold_time";
|
||||
static constexpr auto kIp = "ip";
|
||||
static constexpr auto kJournalMode = "journal_mode";
|
||||
static constexpr auto kJournalSizeLimit = "journal_size_limit";
|
||||
static constexpr auto kLedgersInQueue = "ledgers_in_queue";
|
||||
static constexpr auto kLimit = "limit";
|
||||
static constexpr auto kLogInterval = "log_interval";
|
||||
static constexpr auto kMaxDivergedTime = "max_diverged_time";
|
||||
static constexpr auto kMaxLedgerCountsToStore = "max_ledger_counts_to_store";
|
||||
static constexpr auto kMaxUnknownTime = "max_unknown_time";
|
||||
static constexpr auto kMaximumTxnInLedger = "maximum_txn_in_ledger";
|
||||
static constexpr auto kMaximumTxnPerAccount = "maximum_txn_per_account";
|
||||
static constexpr auto kMemoryLevel = "memory_level";
|
||||
static constexpr auto kMinLedgersToComputeSizeLimit = "min_ledgers_to_compute_size_limit";
|
||||
static constexpr auto kMinimumEscalationMultiplier = "minimum_escalation_multiplier";
|
||||
static constexpr auto kMinimumLastLedgerBuffer = "minimum_last_ledger_buffer";
|
||||
static constexpr auto kMinimumQueueSize = "minimum_queue_size";
|
||||
static constexpr auto kMinimumTxnInLedger = "minimum_txn_in_ledger";
|
||||
static constexpr auto kMinimumTxnInLedgerStandalone = "minimum_txn_in_ledger_standalone";
|
||||
static constexpr auto kNormalConsensusIncreasePercent = "normal_consensus_increase_percent";
|
||||
static constexpr auto kNudbBlockSize = "nudb_block_size";
|
||||
static constexpr auto kOnlineDelete = "online_delete";
|
||||
static constexpr auto kOpenFiles = "open_files";
|
||||
static constexpr auto kOptions = "options";
|
||||
static constexpr auto kOverlay = "overlay";
|
||||
static constexpr auto kOwnerReserve = "owner_reserve";
|
||||
static constexpr auto kPageSize = "page_size";
|
||||
static constexpr auto kPassword = "password";
|
||||
static constexpr auto kPath = "path";
|
||||
static constexpr auto kPermessageDeflate = "permessage_deflate";
|
||||
static constexpr auto kPort = "port";
|
||||
static constexpr auto kPrefix = "prefix";
|
||||
static constexpr auto kProtocol = "protocol";
|
||||
static constexpr auto kRecoveryWaitSeconds = "recovery_wait_seconds";
|
||||
static constexpr auto kReferenceFee = "reference_fee";
|
||||
static constexpr auto kRelayTime = "relay_time";
|
||||
static constexpr auto kRetrySequencePercent = "retry_sequence_percent";
|
||||
static constexpr auto kRqBundle = "rq_bundle";
|
||||
static constexpr auto kSafetyLevel = "safety_level";
|
||||
static constexpr auto kSecureGateway = "secure_gateway";
|
||||
static constexpr auto kSendQueueLimit = "send_queue_limit";
|
||||
static constexpr auto kServer = "server";
|
||||
static constexpr auto kServerMaxWindowBits = "server_max_window_bits";
|
||||
static constexpr auto kServerNoContextTakeover = "server_no_context_takeover";
|
||||
static constexpr auto kSlowConsensusDecreasePercent = "slow_consensus_decrease_percent";
|
||||
static constexpr auto kSslCert = "ssl_cert";
|
||||
static constexpr auto kSslCertChain = "ssl_cert_chain";
|
||||
static constexpr auto kSslChain = "ssl_chain";
|
||||
static constexpr auto kSslCiphers = "ssl_ciphers";
|
||||
static constexpr auto kSslClientCa = "ssl_client_ca";
|
||||
static constexpr auto kSslKey = "ssl_key";
|
||||
static constexpr auto kSynchronous = "synchronous";
|
||||
static constexpr auto kTargetTxnInLedger = "target_txn_in_ledger";
|
||||
static constexpr auto kTempStore = "temp_store";
|
||||
static constexpr auto kTxEnable = "tx_enable";
|
||||
static constexpr auto kTxMetrics = "tx_metrics";
|
||||
static constexpr auto kTxMinPeers = "tx_min_peers";
|
||||
static constexpr auto kTxRelayPercentage = "tx_relay_percentage";
|
||||
static constexpr auto kType = "type";
|
||||
static constexpr auto kUniversalCompaction = "universal_compaction";
|
||||
static constexpr auto kUnl = "unl";
|
||||
static constexpr auto kUseTxTables = "use_tx_tables";
|
||||
static constexpr auto kUser = "user";
|
||||
static constexpr auto kVpBaseSquelchEnable = "vp_base_squelch_enable";
|
||||
static constexpr auto kVpBaseSquelchMaxSelectedPeers = "vp_base_squelch_max_selected_peers";
|
||||
static constexpr auto kVpEnable = "vp_enable";
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,11 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ inline bool
|
||||
JobQueue::Coro::post()
|
||||
{
|
||||
{
|
||||
std::scoped_lock const lk(mutex_run_);
|
||||
std::scoped_lock const lk(mutexRun_);
|
||||
running_ = true;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ JobQueue::Coro::post()
|
||||
}
|
||||
|
||||
// The coroutine will not run. Clean up running_.
|
||||
std::scoped_lock const lk(mutex_run_);
|
||||
std::scoped_lock const lk(mutexRun_);
|
||||
running_ = false;
|
||||
cv_.notify_all();
|
||||
return false;
|
||||
@@ -68,7 +68,7 @@ inline void
|
||||
JobQueue::Coro::resume()
|
||||
{
|
||||
{
|
||||
std::scoped_lock const lk(mutex_run_);
|
||||
std::scoped_lock const lk(mutexRun_);
|
||||
running_ = true;
|
||||
}
|
||||
{
|
||||
@@ -92,7 +92,7 @@ JobQueue::Coro::resume()
|
||||
}
|
||||
detail::getLocalValues().release();
|
||||
detail::getLocalValues().reset(saved);
|
||||
std::scoped_lock const lk(mutex_run_);
|
||||
std::scoped_lock const lk(mutexRun_);
|
||||
running_ = false;
|
||||
cv_.notify_all();
|
||||
}
|
||||
@@ -127,7 +127,7 @@ JobQueue::Coro::expectEarlyExit()
|
||||
inline void
|
||||
JobQueue::Coro::join()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(mutex_run_);
|
||||
std::unique_lock<std::mutex> lk(mutexRun_);
|
||||
cv_.wait(lk, [this]() { return !running_; });
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,16 @@
|
||||
#include <xrpl/basics/UnorderedContainers.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/basics/hardened_hash.h>
|
||||
#include <xrpl/beast/container/aged_unordered_map.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -19,12 +25,14 @@ enum class HashRouterFlags : std::uint16_t {
|
||||
HELD = 0x08, // Held by LedgerMaster after potential processing failure
|
||||
TRUSTED = 0x10, // Comes from a trusted source
|
||||
|
||||
// Private flags (used internally in apply.cpp)
|
||||
// Do not attempt to read, set, or reuse.
|
||||
// Private flags. Each group is owned by one file; do not read, set, or
|
||||
// reuse a flag outside the file noted.
|
||||
// Used in apply.cpp
|
||||
PRIVATE1 = 0x0100,
|
||||
PRIVATE2 = 0x0200,
|
||||
PRIVATE3 = 0x0400,
|
||||
PRIVATE4 = 0x0800,
|
||||
// Used in EscrowFinish.cpp
|
||||
PRIVATE5 = 0x1000,
|
||||
PRIVATE6 = 0x2000
|
||||
};
|
||||
@@ -119,7 +127,7 @@ private:
|
||||
}
|
||||
|
||||
[[nodiscard]] HashRouterFlags
|
||||
getFlags(void) const
|
||||
getFlags() const
|
||||
{
|
||||
return flags_;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/core/ClosureCounter.h>
|
||||
#include <xrpl/core/LoadEvent.h>
|
||||
#include <xrpl/core/LoadMonitor.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -127,7 +132,7 @@ private:
|
||||
std::function<void()> job_;
|
||||
std::shared_ptr<LoadEvent> loadEvent_;
|
||||
std::string name_;
|
||||
clock_type::time_point queue_time_;
|
||||
clock_type::time_point queueTime_;
|
||||
};
|
||||
|
||||
using JobCounter = ClosureCounter<void>;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <xrpl/basics/LocalValue.h>
|
||||
#include <xrpl/core/ClosureCounter.h>
|
||||
#include <xrpl/core/JobTypeData.h>
|
||||
#include <xrpl/core/JobTypes.h>
|
||||
#include <xrpl/core/detail/Workers.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
@@ -12,10 +11,27 @@
|
||||
// `boost/context/pooled_fixedsize_stack.hpp`, whose `.malloc()` / `.free()`
|
||||
// member calls on `boost::pool` collide with MSVC's `_CRTDBG_MAP_ALLOC` macros
|
||||
// in Debug builds (see cmake/XrplCompiler.cmake).
|
||||
#include <xrpl/beast/insight/Collector.h>
|
||||
#include <xrpl/beast/insight/Gauge.h>
|
||||
#include <xrpl/beast/insight/Hook.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/Job.h>
|
||||
#include <xrpl/core/LoadEvent.h>
|
||||
|
||||
#include <boost/context/protected_fixedsize_stack.hpp>
|
||||
#include <boost/coroutine2/coroutine.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -52,7 +68,7 @@ public:
|
||||
std::string name_;
|
||||
bool running_{false};
|
||||
std::mutex mutex_;
|
||||
std::mutex mutex_run_;
|
||||
std::mutex mutexRun_;
|
||||
std::condition_variable cv_;
|
||||
boost::coroutines2::coroutine<void>::push_type* yield_{};
|
||||
boost::coroutines2::coroutine<void>::pull_type coro_;
|
||||
@@ -112,7 +128,7 @@ public:
|
||||
resume();
|
||||
|
||||
/** Returns true if the Coro is still runnable (has not returned). */
|
||||
bool
|
||||
[[nodiscard]] bool
|
||||
runnable() const;
|
||||
|
||||
/** Once called, the Coro allows early exit without an assert. */
|
||||
@@ -138,16 +154,14 @@ public:
|
||||
|
||||
@param type The type of job.
|
||||
@param name Name of the job.
|
||||
@param jobHandler Lambda with signature void (Job&). Called when the
|
||||
job is executed.
|
||||
@param jobHandler Callable with signature void(). Called when the job is executed.
|
||||
|
||||
@return true if jobHandler added to queue.
|
||||
*/
|
||||
template <
|
||||
typename JobHandler,
|
||||
typename = std::enable_if_t<std::is_same_v<decltype(std::declval<JobHandler&&>()()), void>>>
|
||||
template <typename JobHandler>
|
||||
bool
|
||||
addJob(JobType type, std::string const& name, JobHandler&& jobHandler)
|
||||
requires(std::is_void_v<std::invoke_result_t<JobHandler>>)
|
||||
{
|
||||
if (auto optionalCountedJob = jobCounter_.wrap(std::forward<JobHandler>(jobHandler)))
|
||||
{
|
||||
@@ -246,7 +260,7 @@ private:
|
||||
// Statistics tracking
|
||||
perf::PerfLog& perfLog_;
|
||||
beast::insight::Collector::ptr collector_;
|
||||
beast::insight::Gauge job_count_;
|
||||
beast::insight::Gauge jobCount_;
|
||||
beast::insight::Hook hook_;
|
||||
|
||||
std::condition_variable cv_;
|
||||
@@ -384,7 +398,7 @@ private:
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
#include <xrpl/core/Coro.ipp>
|
||||
#include <xrpl/core/Coro.ipp> // IWYU pragma: keep
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/beast/insight/Collector.h>
|
||||
#include <xrpl/beast/insight/Event.h>
|
||||
#include <xrpl/core/Job.h>
|
||||
#include <xrpl/core/JobTypeInfo.h>
|
||||
#include <xrpl/core/LoadMonitor.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user