mirror of
https://github.com/XRPLF/rippled.git
synced 2026-01-29 19:15:26 +00:00
Compare commits
7 Commits
ximinez/fi
...
pratik/Mov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2ec087fe2 | ||
|
|
a6b0671f21 | ||
|
|
9d08722cd0 | ||
|
|
6e17998acb | ||
|
|
72ad34d214 | ||
|
|
c9dd2d73e2 | ||
|
|
63d91b24b9 |
@@ -37,7 +37,7 @@ BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
ColumnLimit: 120
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
|
||||
8
.github/actions/generate-version/action.yml
vendored
8
.github/actions/generate-version/action.yml
vendored
@@ -17,10 +17,8 @@ runs:
|
||||
VERSION: ${{ github.ref_name }}
|
||||
run: echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
|
||||
|
||||
# When a tag is not pushed, then the version (e.g. 1.2.3-b0) is extracted
|
||||
# from the BuildInfo.cpp file and the shortened commit hash appended to it.
|
||||
# We use a plus sign instead of a hyphen because Conan recipe versions do
|
||||
# not support two hyphens.
|
||||
# When a tag is not pushed, then the version is extracted from the
|
||||
# BuildInfo.cpp file and the shortened commit hash appended to it.
|
||||
- name: Generate version for non-tag event
|
||||
if: ${{ github.event_name != 'tag' }}
|
||||
shell: bash
|
||||
@@ -34,7 +32,7 @@ runs:
|
||||
|
||||
echo 'Appending shortened commit hash to version.'
|
||||
SHA='${{ github.sha }}'
|
||||
VERSION="${VERSION}+${SHA:0:7}"
|
||||
VERSION="${VERSION}-${SHA:0:7}"
|
||||
|
||||
echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
|
||||
|
||||
|
||||
2
.github/actions/setup-conan/action.yml
vendored
2
.github/actions/setup-conan/action.yml
vendored
@@ -31,7 +31,7 @@ runs:
|
||||
conan config install conan/profiles/ -tf $(conan config home)/profiles/
|
||||
|
||||
echo 'Conan profile:'
|
||||
conan profile show --profile ci
|
||||
conan profile show
|
||||
|
||||
- name: Set up Conan remote
|
||||
shell: bash
|
||||
|
||||
@@ -19,6 +19,7 @@ libxrpl.protocol > xrpl.json
|
||||
libxrpl.protocol > xrpl.protocol
|
||||
libxrpl.resource > xrpl.basics
|
||||
libxrpl.resource > xrpl.json
|
||||
libxrpl.resource > xrpl.protocol
|
||||
libxrpl.resource > xrpl.resource
|
||||
libxrpl.server > xrpl.basics
|
||||
libxrpl.server > xrpl.json
|
||||
|
||||
2
.github/scripts/strategy-matrix/generate.py
vendored
2
.github/scripts/strategy-matrix/generate.py
vendored
@@ -44,7 +44,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
# We build and test all configurations by default, except for Windows in
|
||||
# Debug, because it is too slow, as well as when code coverage is
|
||||
# enabled as that mode already runs the tests.
|
||||
build_only = False
|
||||
build_only = True
|
||||
if os["distro_name"] == "windows" and build_type == "Debug":
|
||||
build_only = True
|
||||
|
||||
|
||||
1
.github/workflows/on-pr.yml
vendored
1
.github/workflows/on-pr.yml
vendored
@@ -59,7 +59,6 @@ jobs:
|
||||
# Keep the paths below in sync with those in `on-trigger.yml`.
|
||||
.github/actions/build-deps/**
|
||||
.github/actions/build-test/**
|
||||
.github/actions/generate-version/**
|
||||
.github/actions/setup-conan/**
|
||||
.github/scripts/strategy-matrix/**
|
||||
.github/workflows/reusable-build.yml
|
||||
|
||||
1
.github/workflows/on-trigger.yml
vendored
1
.github/workflows/on-trigger.yml
vendored
@@ -16,7 +16,6 @@ on:
|
||||
# Keep the paths below in sync with those in `on-pr.yml`.
|
||||
- ".github/actions/build-deps/**"
|
||||
- ".github/actions/build-test/**"
|
||||
- ".github/actions/generate-version/**"
|
||||
- ".github/actions/setup-conan/**"
|
||||
- ".github/scripts/strategy-matrix/**"
|
||||
- ".github/workflows/reusable-build.yml"
|
||||
|
||||
@@ -125,8 +125,6 @@ jobs:
|
||||
subtract: ${{ inputs.nproc_subtract }}
|
||||
|
||||
- name: Setup Conan
|
||||
env:
|
||||
SANITIZERS: ${{ inputs.sanitizers }}
|
||||
uses: ./.github/actions/setup-conan
|
||||
|
||||
- name: Build dependencies
|
||||
|
||||
41
.github/workflows/reusable-upload-recipe.yml
vendored
41
.github/workflows/reusable-upload-recipe.yml
vendored
@@ -49,6 +49,10 @@ jobs:
|
||||
id: version
|
||||
uses: ./.github/actions/generate-version
|
||||
|
||||
- name: Determine recipe reference
|
||||
id: ref
|
||||
run: echo "ref=xrpl/${{ steps.version.outputs.version }}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Set up Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
with:
|
||||
@@ -58,40 +62,17 @@ jobs:
|
||||
- name: Log into Conan remote
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
REMOTE_USERNAME: ${{ secrets.remote_username }}
|
||||
REMOTE_PASSWORD: ${{ secrets.remote_password }}
|
||||
REMOTE_USERNAME: ${{ inputs.remote_username }}
|
||||
REMOTE_PASSWORD: ${{ inputs.remote_password }}
|
||||
run: conan remote login "${REMOTE_NAME}" "${REMOTE_USERNAME}" --password "${REMOTE_PASSWORD}"
|
||||
|
||||
- name: Upload Conan recipe (version)
|
||||
- name: Upload Conan recipe
|
||||
env:
|
||||
RECIPE_REF: ${{ steps.ref.outputs.ref }}
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
run: |
|
||||
conan export . --version=${{ steps.version.outputs.version }}
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }}
|
||||
|
||||
- name: Upload Conan recipe (develop)
|
||||
if: ${{ github.ref == 'refs/heads/develop' }}
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
run: |
|
||||
conan export . --version=develop
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/develop
|
||||
|
||||
- name: Upload Conan recipe (rc)
|
||||
if: ${{ startsWith(github.ref, 'refs/heads/release') }}
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
run: |
|
||||
conan export . --version=rc
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/rc
|
||||
|
||||
- name: Upload Conan recipe (release)
|
||||
if: ${{ github.event_name == 'tag' }}
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
run: |
|
||||
conan export . --version=release
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/release
|
||||
conan export .
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" ${RECIPE_REF}
|
||||
|
||||
outputs:
|
||||
ref: xrpl/${{ steps.version.outputs.version }}
|
||||
ref: ${{ steps.ref.outputs.ref }}
|
||||
|
||||
3
.github/workflows/upload-conan-deps.yml
vendored
3
.github/workflows/upload-conan-deps.yml
vendored
@@ -84,8 +84,6 @@ jobs:
|
||||
subtract: ${{ env.NPROC_SUBTRACT }}
|
||||
|
||||
- name: Setup Conan
|
||||
env:
|
||||
SANITIZERS: ${{ matrix.sanitizers }}
|
||||
uses: ./.github/actions/setup-conan
|
||||
with:
|
||||
remote_name: ${{ env.CONAN_REMOTE_NAME }}
|
||||
@@ -100,7 +98,6 @@ jobs:
|
||||
# Set the verbosity to "quiet" for Windows to avoid an excessive
|
||||
# amount of logs. For other OSes, the "verbose" logs are more useful.
|
||||
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
|
||||
sanitizers: ${{ matrix.sanitizers }}
|
||||
|
||||
- name: Log into Conan remote
|
||||
if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
||||
|
||||
4
BUILD.md
4
BUILD.md
@@ -148,8 +148,8 @@ function extract_version {
|
||||
}
|
||||
|
||||
# Define which recipes to export.
|
||||
recipes=('ed25519' 'grpc' 'nudb' 'openssl' 'secp256k1' 'snappy' 'soci')
|
||||
folders=('all' 'all' 'all' '3.x.x' 'all' 'all' 'all')
|
||||
recipes=('ed25519' 'grpc' 'openssl' 'secp256k1' 'snappy' 'soci')
|
||||
folders=('all' 'all' '3.x.x' 'all' 'all' 'all')
|
||||
|
||||
# Selectively check out the recipes from our CCI fork.
|
||||
cd external
|
||||
|
||||
@@ -8,9 +8,7 @@ if(POLICY CMP0077)
|
||||
endif()
|
||||
|
||||
# Fix "unrecognized escape" issues when passing CMAKE_MODULE_PATH on Windows.
|
||||
if(DEFINED CMAKE_MODULE_PATH)
|
||||
file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH)
|
||||
endif()
|
||||
file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
project(xrpl)
|
||||
|
||||
@@ -13,7 +13,6 @@ include_guard(GLOBAL)
|
||||
set(is_clang FALSE)
|
||||
set(is_gcc FALSE)
|
||||
set(is_msvc FALSE)
|
||||
set(is_xcode FALSE)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # Clang or AppleClang
|
||||
set(is_clang TRUE)
|
||||
@@ -25,11 +24,6 @@ else()
|
||||
message(FATAL_ERROR "Unsupported C++ compiler: ${CMAKE_CXX_COMPILER_ID}")
|
||||
endif()
|
||||
|
||||
# Xcode generator detection
|
||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(is_xcode TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Operating system detection
|
||||
|
||||
@@ -32,14 +32,14 @@ target_protobuf_sources(xrpl.libpb xrpl/proto
|
||||
|
||||
target_compile_options(xrpl.libpb
|
||||
PUBLIC
|
||||
$<$<BOOL:${is_msvc}>:-wd4996>
|
||||
$<$<BOOL:${is_xcode}>:
|
||||
$<$<BOOL:${MSVC}>:-wd4996>
|
||||
$<$<BOOL:${XCODE}>:
|
||||
--system-header-prefix="google/protobuf"
|
||||
-Wno-deprecated-dynamic-exception-spec
|
||||
>
|
||||
PRIVATE
|
||||
$<$<BOOL:${is_msvc}>:-wd4065>
|
||||
$<$<NOT:$<BOOL:${is_msvc}>>:-Wno-deprecated-declarations>
|
||||
$<$<BOOL:${MSVC}>:-wd4065>
|
||||
$<$<NOT:$<BOOL:${MSVC}>>:-Wno-deprecated-declarations>
|
||||
)
|
||||
|
||||
target_link_libraries(xrpl.libpb
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
|
||||
include(create_symbolic_link)
|
||||
|
||||
# If no suffix is defined for executables (e.g. Windows uses .exe but Linux
|
||||
# and macOS use none), then explicitly set it to the empty string.
|
||||
if(NOT DEFINED suffix)
|
||||
set(suffix "")
|
||||
endif()
|
||||
|
||||
install (
|
||||
TARGETS
|
||||
common
|
||||
|
||||
@@ -4,11 +4,6 @@
|
||||
|
||||
include(CompilationEnv)
|
||||
|
||||
# Set defaults for optional variables to avoid uninitialized variable warnings
|
||||
if(NOT DEFINED voidstar)
|
||||
set(voidstar OFF)
|
||||
endif()
|
||||
|
||||
add_library (opts INTERFACE)
|
||||
add_library (Xrpl::opts ALIAS opts)
|
||||
target_compile_definitions (opts
|
||||
@@ -57,7 +52,7 @@ add_library (xrpl_syslibs INTERFACE)
|
||||
add_library (Xrpl::syslibs ALIAS xrpl_syslibs)
|
||||
target_link_libraries (xrpl_syslibs
|
||||
INTERFACE
|
||||
$<$<BOOL:${is_msvc}>:
|
||||
$<$<BOOL:${MSVC}>:
|
||||
legacy_stdio_definitions.lib
|
||||
Shlwapi
|
||||
kernel32
|
||||
@@ -74,10 +69,10 @@ target_link_libraries (xrpl_syslibs
|
||||
odbccp32
|
||||
crypt32
|
||||
>
|
||||
$<$<NOT:$<BOOL:${is_msvc}>>:dl>
|
||||
$<$<NOT:$<OR:$<BOOL:${is_msvc}>,$<BOOL:${is_macos}>>>:rt>)
|
||||
$<$<NOT:$<BOOL:${MSVC}>>:dl>
|
||||
$<$<NOT:$<OR:$<BOOL:${MSVC}>,$<BOOL:${APPLE}>>>:rt>)
|
||||
|
||||
if (NOT is_msvc)
|
||||
if (NOT MSVC)
|
||||
set (THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package (Threads)
|
||||
target_link_libraries (xrpl_syslibs INTERFACE Threads::Threads)
|
||||
|
||||
@@ -43,10 +43,7 @@
|
||||
include(CompilationEnv)
|
||||
|
||||
# Read environment variable
|
||||
set(SANITIZERS "")
|
||||
if(DEFINED ENV{SANITIZERS})
|
||||
set(SANITIZERS "$ENV{SANITIZERS}")
|
||||
endif()
|
||||
set(SANITIZERS $ENV{SANITIZERS})
|
||||
|
||||
# Set SANITIZERS_ENABLED flag for use in other modules
|
||||
if(SANITIZERS MATCHES "address|thread|undefinedbehavior")
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
|
||||
include(CompilationEnv)
|
||||
|
||||
set(is_ci FALSE)
|
||||
if(DEFINED ENV{CI})
|
||||
if("$ENV{CI}" STREQUAL "true")
|
||||
set(is_ci TRUE)
|
||||
endif()
|
||||
if("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true")
|
||||
set(is_ci TRUE)
|
||||
else()
|
||||
set(is_ci FALSE)
|
||||
endif()
|
||||
|
||||
get_directory_property(has_parent PARENT_DIRECTORY)
|
||||
|
||||
@@ -30,6 +30,7 @@ target_link_libraries(xrpl_boost
|
||||
Boost::process
|
||||
Boost::program_options
|
||||
Boost::regex
|
||||
Boost::system
|
||||
Boost::thread)
|
||||
if(Boost_COMPILER)
|
||||
target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking)
|
||||
|
||||
14
conan.lock
14
conan.lock
@@ -11,7 +11,7 @@
|
||||
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103",
|
||||
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
|
||||
"openssl/3.5.4#1b986e61b38fdfda3b40bebc1b234393%1768312656.257",
|
||||
"nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32",
|
||||
"nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1765850143.957",
|
||||
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
|
||||
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
|
||||
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
|
||||
@@ -23,7 +23,7 @@
|
||||
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
|
||||
"c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336",
|
||||
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
|
||||
"boost/1.90.0#d5e8defe7355494953be18524a7f135b%1765955095.179",
|
||||
"boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1765850172.862",
|
||||
"abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993"
|
||||
],
|
||||
"build_requires": [
|
||||
@@ -42,22 +42,18 @@
|
||||
],
|
||||
"python_requires": [],
|
||||
"overrides": {
|
||||
"boost/1.90.0#d5e8defe7355494953be18524a7f135b": [
|
||||
null,
|
||||
"boost/1.90.0"
|
||||
],
|
||||
"protobuf/5.27.0": [
|
||||
"protobuf/6.32.1"
|
||||
],
|
||||
"lz4/1.9.4": [
|
||||
"lz4/1.10.0"
|
||||
],
|
||||
"boost/1.83.0": [
|
||||
"boost/1.88.0"
|
||||
],
|
||||
"sqlite3/3.44.2": [
|
||||
"sqlite3/3.49.1"
|
||||
],
|
||||
"boost/1.83.0": [
|
||||
"boost/1.90.0"
|
||||
],
|
||||
"lz4/[>=1.9.4 <2]": [
|
||||
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
|
||||
]
|
||||
|
||||
@@ -131,7 +131,7 @@ class Xrpl(ConanFile):
|
||||
transitive_headers_opt = (
|
||||
{"transitive_headers": True} if conan_version.split(".")[0] == "2" else {}
|
||||
)
|
||||
self.requires("boost/1.90.0", force=True, **transitive_headers_opt)
|
||||
self.requires("boost/1.88.0", force=True, **transitive_headers_opt)
|
||||
self.requires("date/3.0.4", **transitive_headers_opt)
|
||||
self.requires("lz4/1.10.0", force=True)
|
||||
self.requires("protobuf/6.32.1", force=True)
|
||||
@@ -203,6 +203,7 @@ class Xrpl(ConanFile):
|
||||
"boost::program_options",
|
||||
"boost::process",
|
||||
"boost::regex",
|
||||
"boost::system",
|
||||
"boost::thread",
|
||||
"date::date",
|
||||
"ed25519::ed25519",
|
||||
|
||||
@@ -13,7 +13,9 @@ namespace xrpl {
|
||||
@throws runtime_error
|
||||
*/
|
||||
void
|
||||
extractTarLz4(boost::filesystem::path const& src, boost::filesystem::path const& dst);
|
||||
extractTarLz4(
|
||||
boost::filesystem::path const& src,
|
||||
boost::filesystem::path const& dst);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
using IniFileSections = std::unordered_map<std::string, std::vector<std::string>>;
|
||||
using IniFileSections =
|
||||
std::unordered_map<std::string, std::vector<std::string>>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -85,7 +86,8 @@ public:
|
||||
if (lines_.empty())
|
||||
return "";
|
||||
if (lines_.size() > 1)
|
||||
Throw<std::runtime_error>("A legacy value must have exactly one line. Section: " + name_);
|
||||
Throw<std::runtime_error>(
|
||||
"A legacy value must have exactly one line. Section: " + name_);
|
||||
return lines_[0];
|
||||
}
|
||||
|
||||
@@ -231,7 +233,10 @@ public:
|
||||
The previous value, if any, is overwritten.
|
||||
*/
|
||||
void
|
||||
overwrite(std::string const& section, std::string const& key, std::string const& value);
|
||||
overwrite(
|
||||
std::string const& section,
|
||||
std::string const& key,
|
||||
std::string const& value);
|
||||
|
||||
/** Remove all the key/value pairs from the section.
|
||||
*/
|
||||
@@ -269,7 +274,9 @@ public:
|
||||
bool
|
||||
had_trailing_comments() const
|
||||
{
|
||||
return std::any_of(map_.cbegin(), map_.cend(), [](auto s) { return s.second.had_trailing_comments(); });
|
||||
return std::any_of(map_.cbegin(), map_.cend(), [](auto s) {
|
||||
return s.second.had_trailing_comments();
|
||||
});
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -308,7 +315,10 @@ set(T& target, std::string const& name, Section const& section)
|
||||
*/
|
||||
template <class T>
|
||||
bool
|
||||
set(T& target, T const& defaultValue, std::string const& name, Section const& section)
|
||||
set(T& target,
|
||||
T const& defaultValue,
|
||||
std::string const& name,
|
||||
Section const& section)
|
||||
{
|
||||
bool found_and_valid = set<T>(target, name, section);
|
||||
if (!found_and_valid)
|
||||
@@ -323,7 +333,9 @@ set(T& target, T const& defaultValue, std::string const& name, Section const& se
|
||||
// NOTE This routine might be more clumsy than the previous two
|
||||
template <class T = std::string>
|
||||
T
|
||||
get(Section const& section, std::string const& name, T const& defaultValue = T{})
|
||||
get(Section const& section,
|
||||
std::string const& name,
|
||||
T const& defaultValue = T{})
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -25,7 +25,8 @@ public:
|
||||
Buffer() = default;
|
||||
|
||||
/** Create an uninitialized buffer with the given size. */
|
||||
explicit Buffer(std::size_t size) : p_(size ? new std::uint8_t[size] : nullptr), size_(size)
|
||||
explicit Buffer(std::size_t size)
|
||||
: p_(size ? new std::uint8_t[size] : nullptr), size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -61,7 +62,8 @@ public:
|
||||
/** Move-construct.
|
||||
The other buffer is reset.
|
||||
*/
|
||||
Buffer(Buffer&& other) noexcept : p_(std::move(other.p_)), size_(other.size_)
|
||||
Buffer(Buffer&& other) noexcept
|
||||
: p_(std::move(other.p_)), size_(other.size_)
|
||||
{
|
||||
other.size_ = 0;
|
||||
}
|
||||
@@ -92,7 +94,8 @@ public:
|
||||
{
|
||||
// Ensure the slice isn't a subset of the buffer.
|
||||
XRPL_ASSERT(
|
||||
s.size() == 0 || size_ == 0 || s.data() < p_.get() || s.data() >= p_.get() + size_,
|
||||
s.size() == 0 || size_ == 0 || s.data() < p_.get() ||
|
||||
s.data() >= p_.get() + size_,
|
||||
"xrpl::Buffer::operator=(Slice) : input not a subset");
|
||||
|
||||
if (auto p = alloc(s.size()))
|
||||
|
||||
@@ -36,7 +36,10 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
auto compressed = bf(outCapacity);
|
||||
|
||||
auto compressedSize = LZ4_compress_default(
|
||||
reinterpret_cast<char const*>(in), reinterpret_cast<char*>(compressed), inSize, outCapacity);
|
||||
reinterpret_cast<char const*>(in),
|
||||
reinterpret_cast<char*>(compressed),
|
||||
inSize,
|
||||
outCapacity);
|
||||
if (compressedSize == 0)
|
||||
Throw<std::runtime_error>("lz4 compress: failed");
|
||||
|
||||
@@ -67,8 +70,10 @@ lz4Decompress(
|
||||
Throw<std::runtime_error>("lz4Decompress: integer overflow (output)");
|
||||
|
||||
if (LZ4_decompress_safe(
|
||||
reinterpret_cast<char const*>(in), reinterpret_cast<char*>(decompressed), inSize, decompressedSize) !=
|
||||
decompressedSize)
|
||||
reinterpret_cast<char const*>(in),
|
||||
reinterpret_cast<char*>(decompressed),
|
||||
inSize,
|
||||
decompressedSize) != decompressedSize)
|
||||
Throw<std::runtime_error>("lz4Decompress: failed");
|
||||
|
||||
return decompressedSize;
|
||||
@@ -84,7 +89,11 @@ lz4Decompress(
|
||||
*/
|
||||
template <typename InputStream>
|
||||
std::size_t
|
||||
lz4Decompress(InputStream& in, std::size_t inSize, std::uint8_t* decompressed, std::size_t decompressedSize)
|
||||
lz4Decompress(
|
||||
InputStream& in,
|
||||
std::size_t inSize,
|
||||
std::uint8_t* decompressed,
|
||||
std::size_t decompressedSize)
|
||||
{
|
||||
std::vector<std::uint8_t> compressed;
|
||||
std::uint8_t const* chunk = nullptr;
|
||||
@@ -107,7 +116,9 @@ lz4Decompress(InputStream& in, std::size_t inSize, std::uint8_t* decompressed, s
|
||||
compressed.resize(inSize);
|
||||
}
|
||||
|
||||
chunkSize = chunkSize < (inSize - copiedInSize) ? chunkSize : (inSize - copiedInSize);
|
||||
chunkSize = chunkSize < (inSize - copiedInSize)
|
||||
? chunkSize
|
||||
: (inSize - copiedInSize);
|
||||
|
||||
std::copy(chunk, chunk + chunkSize, compressed.data() + copiedInSize);
|
||||
|
||||
@@ -124,7 +135,8 @@ lz4Decompress(InputStream& in, std::size_t inSize, std::uint8_t* decompressed, s
|
||||
if (in.ByteCount() > (currentBytes + copiedInSize))
|
||||
in.BackUp(in.ByteCount() - currentBytes - copiedInSize);
|
||||
|
||||
if ((copiedInSize == 0 && chunkSize < inSize) || (copiedInSize > 0 && copiedInSize != inSize))
|
||||
if ((copiedInSize == 0 && chunkSize < inSize) ||
|
||||
(copiedInSize > 0 && copiedInSize != inSize))
|
||||
Throw<std::runtime_error>("lz4 decompress: insufficient input size");
|
||||
|
||||
return lz4Decompress(chunk, inSize, decompressed, decompressedSize);
|
||||
|
||||
@@ -56,7 +56,9 @@ private:
|
||||
|
||||
if (m_value != value_type())
|
||||
{
|
||||
std::size_t elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - m_when).count();
|
||||
std::size_t elapsed =
|
||||
std::chrono::duration_cast<std::chrono::seconds>(now - m_when)
|
||||
.count();
|
||||
|
||||
// A span larger than four times the window decays the
|
||||
// value to an insignificant amount so just reset it.
|
||||
|
||||
@@ -108,20 +108,23 @@ 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::throw_policy>
|
||||
class [[nodiscard]] Expected
|
||||
: private boost::outcome_v2::result<T, E, detail::throw_policy>
|
||||
{
|
||||
using Base = boost::outcome_v2::result<T, E, detail::throw_policy>;
|
||||
|
||||
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))
|
||||
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()))
|
||||
constexpr Expected(Unexpected<U> e)
|
||||
: Base(boost::outcome_v2::in_place_type_t<E>{}, std::move(e.value()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -192,7 +195,8 @@ public:
|
||||
// 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::throw_policy>
|
||||
class [[nodiscard]] Expected<void, E>
|
||||
: private boost::outcome_v2::result<void, E, detail::throw_policy>
|
||||
{
|
||||
using Base = boost::outcome_v2::result<void, E, detail::throw_policy>;
|
||||
|
||||
|
||||
@@ -15,7 +15,10 @@ getFileContents(
|
||||
std::optional<std::size_t> maxSize = std::nullopt);
|
||||
|
||||
void
|
||||
writeFileContents(boost::system::error_code& ec, boost::filesystem::path const& destPath, std::string const& contents);
|
||||
writeFileContents(
|
||||
boost::system::error_code& ec,
|
||||
boost::filesystem::path const& destPath,
|
||||
std::string const& contents);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
|
||||
@@ -45,8 +45,8 @@ struct SharedIntrusiveAdoptNoIncrementTag
|
||||
//
|
||||
|
||||
template <class T>
|
||||
concept CAdoptTag =
|
||||
std::is_same_v<T, SharedIntrusiveAdoptIncrementStrongTag> || std::is_same_v<T, SharedIntrusiveAdoptNoIncrementTag>;
|
||||
concept CAdoptTag = std::is_same_v<T, SharedIntrusiveAdoptIncrementStrongTag> ||
|
||||
std::is_same_v<T, SharedIntrusiveAdoptNoIncrementTag>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -122,7 +122,9 @@ public:
|
||||
controlled by the rhs param.
|
||||
*/
|
||||
template <class TT>
|
||||
SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs);
|
||||
SharedIntrusive(
|
||||
StaticCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT> const& rhs);
|
||||
|
||||
/** Create a new SharedIntrusive by statically casting the pointer
|
||||
controlled by the rhs param.
|
||||
@@ -134,7 +136,9 @@ public:
|
||||
controlled by the rhs param.
|
||||
*/
|
||||
template <class TT>
|
||||
SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs);
|
||||
SharedIntrusive(
|
||||
DynamicCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT> const& rhs);
|
||||
|
||||
/** Create a new SharedIntrusive by dynamically casting the pointer
|
||||
controlled by the rhs param.
|
||||
@@ -300,7 +304,9 @@ class SharedWeakUnion
|
||||
// Tagged pointer. Low bit determines if this is a strong or a weak
|
||||
// pointer. The low bit must be masked to zero when converting back to a
|
||||
// pointer. If the low bit is '1', this is a weak pointer.
|
||||
static_assert(alignof(T) >= 2, "Bad alignment: Combo pointer requires low bit to be zero");
|
||||
static_assert(
|
||||
alignof(T) >= 2,
|
||||
"Bad alignment: Combo pointer requires low bit to be zero");
|
||||
|
||||
public:
|
||||
SharedWeakUnion() = default;
|
||||
@@ -444,7 +450,9 @@ make_SharedIntrusive(Args&&... args)
|
||||
auto p = new TT(std::forward<Args>(args)...);
|
||||
|
||||
static_assert(
|
||||
noexcept(SharedIntrusive<TT>(std::declval<TT*>(), std::declval<SharedIntrusiveAdoptNoIncrementTag>())),
|
||||
noexcept(SharedIntrusive<TT>(
|
||||
std::declval<TT*>(),
|
||||
std::declval<SharedIntrusiveAdoptNoIncrementTag>())),
|
||||
"SharedIntrusive constructor should not throw or this can leak "
|
||||
"memory");
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ template <class T>
|
||||
template <CAdoptTag TAdoptTag>
|
||||
SharedIntrusive<T>::SharedIntrusive(T* p, TAdoptTag) noexcept : ptr_{p}
|
||||
{
|
||||
if constexpr (std::is_same_v<TAdoptTag, SharedIntrusiveAdoptIncrementStrongTag>)
|
||||
if constexpr (std::is_same_v<
|
||||
TAdoptTag,
|
||||
SharedIntrusiveAdoptIncrementStrongTag>)
|
||||
{
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
@@ -44,14 +46,16 @@ SharedIntrusive<T>::SharedIntrusive(SharedIntrusive<TT> const& rhs)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive&& rhs) : ptr_{rhs.unsafeExchange(nullptr)}
|
||||
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive&& rhs)
|
||||
: ptr_{rhs.unsafeExchange(nullptr)}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive<TT>&& rhs) : ptr_{rhs.unsafeExchange(nullptr)}
|
||||
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive<TT>&& rhs)
|
||||
: ptr_{rhs.unsafeExchange(nullptr)}
|
||||
{
|
||||
}
|
||||
template <class T>
|
||||
@@ -108,7 +112,9 @@ requires std::convertible_to<TT*, T*>
|
||||
SharedIntrusive<T>&
|
||||
SharedIntrusive<T>::operator=(SharedIntrusive<TT>&& rhs)
|
||||
{
|
||||
static_assert(!std::is_same_v<T, TT>, "This overload should not be instantiated for T == TT");
|
||||
static_assert(
|
||||
!std::is_same_v<T, TT>,
|
||||
"This overload should not be instantiated for T == TT");
|
||||
|
||||
unsafeReleaseAndStore(rhs.unsafeExchange(nullptr));
|
||||
return *this;
|
||||
@@ -133,7 +139,9 @@ template <CAdoptTag TAdoptTag>
|
||||
void
|
||||
SharedIntrusive<T>::adopt(T* p)
|
||||
{
|
||||
if constexpr (std::is_same_v<TAdoptTag, SharedIntrusiveAdoptIncrementStrongTag>)
|
||||
if constexpr (std::is_same_v<
|
||||
TAdoptTag,
|
||||
SharedIntrusiveAdoptIncrementStrongTag>)
|
||||
{
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
@@ -149,7 +157,9 @@ SharedIntrusive<T>::~SharedIntrusive()
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
SharedIntrusive<T>::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs)
|
||||
SharedIntrusive<T>::SharedIntrusive(
|
||||
StaticCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT> const& rhs)
|
||||
: ptr_{[&] {
|
||||
auto p = static_cast<T*>(rhs.unsafeGetRawPtr());
|
||||
if (p)
|
||||
@@ -161,14 +171,18 @@ SharedIntrusive<T>::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusiv
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
SharedIntrusive<T>::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive<TT>&& rhs)
|
||||
SharedIntrusive<T>::SharedIntrusive(
|
||||
StaticCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT>&& rhs)
|
||||
: ptr_{static_cast<T*>(rhs.unsafeExchange(nullptr))}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
SharedIntrusive<T>::SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs)
|
||||
SharedIntrusive<T>::SharedIntrusive(
|
||||
DynamicCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT> const& rhs)
|
||||
: ptr_{[&] {
|
||||
auto p = dynamic_cast<T*>(rhs.unsafeGetRawPtr());
|
||||
if (p)
|
||||
@@ -180,7 +194,9 @@ SharedIntrusive<T>::SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusi
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
SharedIntrusive<T>::SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive<TT>&& rhs)
|
||||
SharedIntrusive<T>::SharedIntrusive(
|
||||
DynamicCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT>&& rhs)
|
||||
{
|
||||
// This can be simplified without the `exchange`, but the `exchange` is kept
|
||||
// in anticipation of supporting atomic operations.
|
||||
@@ -299,7 +315,8 @@ WeakIntrusive<T>::WeakIntrusive(WeakIntrusive&& rhs) : ptr_{rhs.ptr_}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
WeakIntrusive<T>::WeakIntrusive(SharedIntrusive<T> const& rhs) : ptr_{rhs.unsafeGetRawPtr()}
|
||||
WeakIntrusive<T>::WeakIntrusive(SharedIntrusive<T> const& rhs)
|
||||
: ptr_{rhs.unsafeGetRawPtr()}
|
||||
{
|
||||
if (ptr_)
|
||||
ptr_->addWeakRef();
|
||||
|
||||
@@ -160,19 +160,22 @@ private:
|
||||
See description of the `refCounts` field for a fuller description of
|
||||
this field.
|
||||
*/
|
||||
static constexpr FieldType partialDestroyStartedMask = (one << (FieldTypeBits - 1));
|
||||
static constexpr FieldType partialDestroyStartedMask =
|
||||
(one << (FieldTypeBits - 1));
|
||||
|
||||
/** Flag that is set when the partialDestroy function has finished running
|
||||
|
||||
See description of the `refCounts` field for a fuller description of
|
||||
this field.
|
||||
*/
|
||||
static constexpr FieldType partialDestroyFinishedMask = (one << (FieldTypeBits - 2));
|
||||
static constexpr FieldType partialDestroyFinishedMask =
|
||||
(one << (FieldTypeBits - 2));
|
||||
|
||||
/** Mask that will zero out all the `count` bits and leave the tag bits
|
||||
unchanged.
|
||||
*/
|
||||
static constexpr FieldType tagMask = partialDestroyStartedMask | partialDestroyFinishedMask;
|
||||
static constexpr FieldType tagMask =
|
||||
partialDestroyStartedMask | partialDestroyFinishedMask;
|
||||
|
||||
/** Mask that will zero out the `tag` bits and leave the count bits
|
||||
unchanged.
|
||||
@@ -181,11 +184,13 @@ private:
|
||||
|
||||
/** Mask that will zero out everything except the strong count.
|
||||
*/
|
||||
static constexpr FieldType strongMask = ((one << StrongCountNumBits) - 1) & valueMask;
|
||||
static constexpr FieldType strongMask =
|
||||
((one << StrongCountNumBits) - 1) & valueMask;
|
||||
|
||||
/** Mask that will zero out everything except the weak count.
|
||||
*/
|
||||
static constexpr FieldType weakMask = (((one << WeakCountNumBits) - 1) << StrongCountNumBits) & valueMask;
|
||||
static constexpr FieldType weakMask =
|
||||
(((one << WeakCountNumBits) - 1) << StrongCountNumBits) & valueMask;
|
||||
|
||||
/** Unpack the count and tag fields from the packed atomic integer form. */
|
||||
struct RefCountPair
|
||||
@@ -210,8 +215,10 @@ private:
|
||||
FieldType
|
||||
combinedValue() const noexcept;
|
||||
|
||||
static constexpr CountType maxStrongValue = static_cast<CountType>((one << StrongCountNumBits) - 1);
|
||||
static constexpr CountType maxWeakValue = static_cast<CountType>((one << WeakCountNumBits) - 1);
|
||||
static constexpr CountType maxStrongValue =
|
||||
static_cast<CountType>((one << StrongCountNumBits) - 1);
|
||||
static constexpr CountType maxWeakValue =
|
||||
static_cast<CountType>((one << WeakCountNumBits) - 1);
|
||||
/** Put an extra margin to detect when running up against limits.
|
||||
This is only used in debug code, and is useful if we reduce the
|
||||
number of bits in the strong and weak counts (to 16 and 14 bits).
|
||||
@@ -267,7 +274,8 @@ IntrusiveRefCounts::releaseStrongRef() const
|
||||
}
|
||||
}
|
||||
|
||||
if (refCounts.compare_exchange_weak(prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
if (refCounts.compare_exchange_weak(
|
||||
prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
{
|
||||
// Can't be in partial destroy because only decrementing the strong
|
||||
// count to zero can start a partial destroy, and that can't happen
|
||||
@@ -323,7 +331,8 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
|
||||
action = partialDestroy;
|
||||
}
|
||||
}
|
||||
if (refCounts.compare_exchange_weak(prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
if (refCounts.compare_exchange_weak(
|
||||
prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(!(prevIntVal & partialDestroyStartedMask)),
|
||||
@@ -367,7 +376,8 @@ IntrusiveRefCounts::checkoutStrongRefFromWeak() const noexcept
|
||||
auto curValue = RefCountPair{1, 1}.combinedValue();
|
||||
auto desiredValue = RefCountPair{2, 1}.combinedValue();
|
||||
|
||||
while (!refCounts.compare_exchange_weak(curValue, desiredValue, std::memory_order_acq_rel))
|
||||
while (!refCounts.compare_exchange_weak(
|
||||
curValue, desiredValue, std::memory_order_acq_rel))
|
||||
{
|
||||
RefCountPair const prev{curValue};
|
||||
if (!prev.strong)
|
||||
@@ -396,15 +406,20 @@ inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
auto v = refCounts.load(std::memory_order_acquire);
|
||||
XRPL_ASSERT((!(v & valueMask)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero");
|
||||
XRPL_ASSERT(
|
||||
(!(v & valueMask)),
|
||||
"xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero");
|
||||
auto t = v & tagMask;
|
||||
XRPL_ASSERT((!t || t == tagMask), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag");
|
||||
XRPL_ASSERT(
|
||||
(!t || t == tagMask),
|
||||
"xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag");
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline IntrusiveRefCounts::RefCountPair::RefCountPair(IntrusiveRefCounts::FieldType v) noexcept
|
||||
inline IntrusiveRefCounts::RefCountPair::RefCountPair(
|
||||
IntrusiveRefCounts::FieldType v) noexcept
|
||||
: strong{static_cast<CountType>(v & strongMask)}
|
||||
, weak{static_cast<CountType>((v & weakMask) >> StrongCountNumBits)}
|
||||
, partialDestroyStartedBit{v & partialDestroyStartedMask}
|
||||
@@ -434,8 +449,10 @@ IntrusiveRefCounts::RefCountPair::combinedValue() const noexcept
|
||||
(strong < checkStrongMaxValue && weak < checkWeakMaxValue),
|
||||
"xrpl::IntrusiveRefCounts::RefCountPair::combinedValue : inputs "
|
||||
"inside range");
|
||||
return (static_cast<IntrusiveRefCounts::FieldType>(weak) << IntrusiveRefCounts::StrongCountNumBits) |
|
||||
static_cast<IntrusiveRefCounts::FieldType>(strong) | partialDestroyStartedBit | partialDestroyFinishedBit;
|
||||
return (static_cast<IntrusiveRefCounts::FieldType>(weak)
|
||||
<< IntrusiveRefCounts::StrongCountNumBits) |
|
||||
static_cast<IntrusiveRefCounts::FieldType>(strong) |
|
||||
partialDestroyStartedBit | partialDestroyFinishedBit;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -443,9 +460,11 @@ inline void
|
||||
partialDestructorFinished(T** o)
|
||||
{
|
||||
T& self = **o;
|
||||
IntrusiveRefCounts::RefCountPair p = self.refCounts.fetch_or(IntrusiveRefCounts::partialDestroyFinishedMask);
|
||||
IntrusiveRefCounts::RefCountPair p =
|
||||
self.refCounts.fetch_or(IntrusiveRefCounts::partialDestroyFinishedMask);
|
||||
XRPL_ASSERT(
|
||||
(!p.partialDestroyFinishedBit && p.partialDestroyStartedBit && !p.strong),
|
||||
(!p.partialDestroyFinishedBit && p.partialDestroyStartedBit &&
|
||||
!p.strong),
|
||||
"xrpl::partialDestructorFinished : not a weak ref");
|
||||
if (!p.weak)
|
||||
{
|
||||
|
||||
@@ -55,7 +55,8 @@ template <class = void>
|
||||
boost::thread_specific_ptr<detail::LocalValues>&
|
||||
getLocalValues()
|
||||
{
|
||||
static boost::thread_specific_ptr<detail::LocalValues> tsp(&detail::LocalValues::cleanup);
|
||||
static boost::thread_specific_ptr<detail::LocalValues> tsp(
|
||||
&detail::LocalValues::cleanup);
|
||||
return tsp;
|
||||
}
|
||||
|
||||
@@ -104,7 +105,9 @@ LocalValue<T>::operator*()
|
||||
}
|
||||
|
||||
return *reinterpret_cast<T*>(
|
||||
lvs->values.emplace(this, std::make_unique<detail::LocalValues::Value<T>>(t_)).first->second->get());
|
||||
lvs->values
|
||||
.emplace(this, std::make_unique<detail::LocalValues::Value<T>>(t_))
|
||||
.first->second->get());
|
||||
}
|
||||
} // namespace xrpl
|
||||
|
||||
|
||||
@@ -39,17 +39,22 @@ private:
|
||||
std::string partition_;
|
||||
|
||||
public:
|
||||
Sink(std::string const& partition, beast::severities::Severity thresh, Logs& logs);
|
||||
Sink(
|
||||
std::string const& partition,
|
||||
beast::severities::Severity thresh,
|
||||
Logs& logs);
|
||||
|
||||
Sink(Sink const&) = delete;
|
||||
Sink&
|
||||
operator=(Sink const&) = delete;
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text) override;
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
override;
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text) override;
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
override;
|
||||
};
|
||||
|
||||
/** Manages a system file containing logged output.
|
||||
@@ -135,7 +140,11 @@ private:
|
||||
};
|
||||
|
||||
std::mutex mutable mutex_;
|
||||
std::map<std::string, std::unique_ptr<beast::Journal::Sink>, boost::beast::iless> sinks_;
|
||||
std::map<
|
||||
std::string,
|
||||
std::unique_ptr<beast::Journal::Sink>,
|
||||
boost::beast::iless>
|
||||
sinks_;
|
||||
beast::severities::Severity thresh_;
|
||||
File file_;
|
||||
bool silent_ = false;
|
||||
@@ -171,7 +180,11 @@ public:
|
||||
partition_severities() const;
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& partition, std::string const& text, bool console);
|
||||
write(
|
||||
beast::severities::Severity level,
|
||||
std::string const& partition,
|
||||
std::string const& text,
|
||||
bool console);
|
||||
|
||||
std::string
|
||||
rotate();
|
||||
@@ -188,7 +201,9 @@ public:
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<beast::Journal::Sink>
|
||||
makeSink(std::string const& partition, beast::severities::Severity startingLevel);
|
||||
makeSink(
|
||||
std::string const& partition,
|
||||
beast::severities::Severity startingLevel);
|
||||
|
||||
public:
|
||||
static LogSeverity
|
||||
|
||||
@@ -74,7 +74,10 @@ struct MantissaRange
|
||||
enum mantissa_scale { small, large };
|
||||
|
||||
explicit constexpr MantissaRange(mantissa_scale scale_)
|
||||
: min(getMin(scale_)), max(min * 10 - 1), log(logTen(min).value_or(-1)), scale(scale_)
|
||||
: min(getMin(scale_))
|
||||
, max(min * 10 - 1)
|
||||
, log(logTen(min).value_or(-1))
|
||||
, scale(scale_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -104,7 +107,8 @@ private:
|
||||
|
||||
// Like std::integral, but only 64-bit integral types.
|
||||
template <class T>
|
||||
concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::uint64_t>;
|
||||
concept Integral64 =
|
||||
std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::uint64_t>;
|
||||
|
||||
/** Number is a floating point type that can represent a wide range of values.
|
||||
*
|
||||
@@ -241,11 +245,22 @@ public:
|
||||
|
||||
Number(rep mantissa);
|
||||
explicit Number(rep mantissa, int exponent);
|
||||
explicit constexpr Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept;
|
||||
explicit constexpr Number(
|
||||
bool negative,
|
||||
internalrep mantissa,
|
||||
int exponent,
|
||||
unchecked) noexcept;
|
||||
// Assume unsigned values are... unsigned. i.e. positive
|
||||
explicit constexpr Number(internalrep mantissa, int exponent, unchecked) noexcept;
|
||||
explicit constexpr Number(
|
||||
internalrep mantissa,
|
||||
int exponent,
|
||||
unchecked) noexcept;
|
||||
// Only unit tests are expected to use this ctor
|
||||
explicit Number(bool negative, internalrep mantissa, int exponent, normalized);
|
||||
explicit Number(
|
||||
bool negative,
|
||||
internalrep mantissa,
|
||||
int exponent,
|
||||
normalized);
|
||||
// Assume unsigned values are... unsigned. i.e. positive
|
||||
explicit Number(internalrep mantissa, int exponent, normalized);
|
||||
|
||||
@@ -295,7 +310,8 @@ public:
|
||||
friend constexpr bool
|
||||
operator==(Number const& x, Number const& y) noexcept
|
||||
{
|
||||
return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_;
|
||||
return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ &&
|
||||
x.exponent_ == y.exponent_;
|
||||
}
|
||||
|
||||
friend constexpr bool
|
||||
@@ -503,25 +519,37 @@ private:
|
||||
class Guard;
|
||||
};
|
||||
|
||||
inline constexpr Number::Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept
|
||||
inline constexpr Number::Number(
|
||||
bool negative,
|
||||
internalrep mantissa,
|
||||
int exponent,
|
||||
unchecked) noexcept
|
||||
: negative_(negative), mantissa_{mantissa}, exponent_{exponent}
|
||||
{
|
||||
}
|
||||
|
||||
inline constexpr Number::Number(internalrep mantissa, int exponent, unchecked) noexcept
|
||||
inline constexpr Number::Number(
|
||||
internalrep mantissa,
|
||||
int exponent,
|
||||
unchecked) noexcept
|
||||
: Number(false, mantissa, exponent, unchecked{})
|
||||
{
|
||||
}
|
||||
|
||||
constexpr static Number numZero{};
|
||||
|
||||
inline Number::Number(bool negative, internalrep mantissa, int exponent, normalized)
|
||||
inline Number::Number(
|
||||
bool negative,
|
||||
internalrep mantissa,
|
||||
int exponent,
|
||||
normalized)
|
||||
: Number(negative, mantissa, exponent, unchecked{})
|
||||
{
|
||||
normalize();
|
||||
}
|
||||
|
||||
inline Number::Number(internalrep mantissa, int exponent, normalized) : Number(false, mantissa, exponent, normalized{})
|
||||
inline Number::Number(internalrep mantissa, int exponent, normalized)
|
||||
: Number(false, mantissa, exponent, normalized{})
|
||||
{
|
||||
}
|
||||
|
||||
@@ -668,13 +696,15 @@ Number::min() noexcept
|
||||
inline Number
|
||||
Number::max() noexcept
|
||||
{
|
||||
return Number{false, std::min(range_.get().max, maxRep), maxExponent, unchecked{}};
|
||||
return Number{
|
||||
false, std::min(range_.get().max, maxRep), maxExponent, unchecked{}};
|
||||
}
|
||||
|
||||
inline Number
|
||||
Number::lowest() noexcept
|
||||
{
|
||||
return Number{true, std::min(range_.get().max, maxRep), maxExponent, unchecked{}};
|
||||
return Number{
|
||||
true, std::min(range_.get().max, maxRep), maxExponent, unchecked{}};
|
||||
}
|
||||
|
||||
inline bool
|
||||
@@ -683,7 +713,8 @@ Number::isnormal() const noexcept
|
||||
MantissaRange const& range = range_;
|
||||
auto const abs_m = mantissa_;
|
||||
return *this == Number{} ||
|
||||
(range.min <= abs_m && abs_m <= range.max && (abs_m <= maxRep || abs_m % 10 == 0) && minExponent <= exponent_ &&
|
||||
(range.min <= abs_m && abs_m <= range.max &&
|
||||
(abs_m <= maxRep || abs_m % 10 == 0) && minExponent <= exponent_ &&
|
||||
exponent_ <= maxExponent);
|
||||
}
|
||||
|
||||
@@ -696,7 +727,10 @@ Number::normalizeToRange(T minMantissa, T maxMantissa) const
|
||||
int exponent = exponent_;
|
||||
|
||||
if constexpr (std::is_unsigned_v<T>)
|
||||
XRPL_ASSERT_PARTS(!negative, "xrpl::Number::normalizeToRange", "Number is non-negative for unsigned range.");
|
||||
XRPL_ASSERT_PARTS(
|
||||
!negative,
|
||||
"xrpl::Number::normalizeToRange",
|
||||
"Number is non-negative for unsigned range.");
|
||||
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
|
||||
|
||||
auto const sign = negative ? -1 : 1;
|
||||
@@ -765,7 +799,8 @@ public:
|
||||
{
|
||||
Number::setround(mode_);
|
||||
}
|
||||
explicit saveNumberRoundMode(Number::rounding_mode mode) noexcept : mode_{mode}
|
||||
explicit saveNumberRoundMode(Number::rounding_mode mode) noexcept
|
||||
: mode_{mode}
|
||||
{
|
||||
}
|
||||
saveNumberRoundMode(saveNumberRoundMode const&) = delete;
|
||||
@@ -782,7 +817,8 @@ class NumberRoundModeGuard
|
||||
saveNumberRoundMode saved_;
|
||||
|
||||
public:
|
||||
explicit NumberRoundModeGuard(Number::rounding_mode mode) noexcept : saved_{Number::setround(mode)}
|
||||
explicit NumberRoundModeGuard(Number::rounding_mode mode) noexcept
|
||||
: saved_{Number::setround(mode)}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -802,7 +838,9 @@ class NumberMantissaScaleGuard
|
||||
MantissaRange::mantissa_scale const saved_;
|
||||
|
||||
public:
|
||||
explicit NumberMantissaScaleGuard(MantissaRange::mantissa_scale scale) noexcept : saved_{Number::getMantissaScale()}
|
||||
explicit NumberMantissaScaleGuard(
|
||||
MantissaRange::mantissa_scale scale) noexcept
|
||||
: saved_{Number::getMantissaScale()}
|
||||
{
|
||||
Number::setMantissaScale(scale);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ namespace xrpl {
|
||||
class Resolver
|
||||
{
|
||||
public:
|
||||
using HandlerType = std::function<void(std::string, std::vector<beast::IP::Endpoint>)>;
|
||||
using HandlerType =
|
||||
std::function<void(std::string, std::vector<beast::IP::Endpoint>)>;
|
||||
|
||||
virtual ~Resolver() = 0;
|
||||
|
||||
@@ -40,7 +41,9 @@ public:
|
||||
}
|
||||
|
||||
virtual void
|
||||
resolve(std::vector<std::string> const& names, HandlerType const& handler) = 0;
|
||||
resolve(
|
||||
std::vector<std::string> const& names,
|
||||
HandlerType const& handler) = 0;
|
||||
/** @} */
|
||||
};
|
||||
|
||||
|
||||
@@ -5,28 +5,34 @@
|
||||
|
||||
namespace xrpl {
|
||||
template <class T>
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(SharedWeakCachePointer const& rhs) = default;
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(
|
||||
SharedWeakCachePointer const& rhs) = default;
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(std::shared_ptr<TT> const& rhs) : combo_{rhs}
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(
|
||||
std::shared_ptr<TT> const& rhs)
|
||||
: combo_{rhs}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(SharedWeakCachePointer&& rhs) = default;
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(
|
||||
SharedWeakCachePointer&& rhs) = default;
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(std::shared_ptr<TT>&& rhs) : combo_{std::move(rhs)}
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(std::shared_ptr<TT>&& rhs)
|
||||
: combo_{std::move(rhs)}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakCachePointer<T>&
|
||||
SharedWeakCachePointer<T>::operator=(SharedWeakCachePointer const& rhs) = default;
|
||||
SharedWeakCachePointer<T>::operator=(SharedWeakCachePointer const& rhs) =
|
||||
default;
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
|
||||
@@ -51,7 +51,11 @@ class SlabAllocator
|
||||
// The extent of the underlying memory block:
|
||||
std::size_t const size_;
|
||||
|
||||
SlabBlock(SlabBlock* next, std::uint8_t* data, std::size_t size, std::size_t item)
|
||||
SlabBlock(
|
||||
SlabBlock* next,
|
||||
std::uint8_t* data,
|
||||
std::size_t size,
|
||||
std::size_t item)
|
||||
: next_(next), p_(data), size_(size)
|
||||
{
|
||||
// We don't need to grab the mutex here, since we're the only
|
||||
@@ -122,7 +126,9 @@ class SlabAllocator
|
||||
void
|
||||
deallocate(std::uint8_t* ptr) noexcept
|
||||
{
|
||||
XRPL_ASSERT(own(ptr), "xrpl::SlabAllocator::SlabBlock::deallocate : own input");
|
||||
XRPL_ASSERT(
|
||||
own(ptr),
|
||||
"xrpl::SlabAllocator::SlabBlock::deallocate : own input");
|
||||
|
||||
std::lock_guard l(m_);
|
||||
|
||||
@@ -156,13 +162,18 @@ public:
|
||||
contexts (e.g. when minimal memory usage is needed) and
|
||||
allows for graceful failure.
|
||||
*/
|
||||
constexpr explicit SlabAllocator(std::size_t extra, std::size_t alloc = 0, std::size_t align = 0)
|
||||
constexpr explicit SlabAllocator(
|
||||
std::size_t extra,
|
||||
std::size_t alloc = 0,
|
||||
std::size_t align = 0)
|
||||
: itemAlignment_(align ? align : alignof(Type))
|
||||
, itemSize_(boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_))
|
||||
, itemSize_(
|
||||
boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_))
|
||||
, slabSize_(alloc)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(itemAlignment_ & (itemAlignment_ - 1)) == 0, "xrpl::SlabAllocator::SlabAllocator : valid alignment");
|
||||
(itemAlignment_ & (itemAlignment_ - 1)) == 0,
|
||||
"xrpl::SlabAllocator::SlabAllocator : valid alignment");
|
||||
}
|
||||
|
||||
SlabAllocator(SlabAllocator const& other) = delete;
|
||||
@@ -211,7 +222,8 @@ public:
|
||||
|
||||
// We want to allocate the memory at a 2 MiB boundary, to make it
|
||||
// possible to use hugepage mappings on Linux:
|
||||
auto buf = boost::alignment::aligned_alloc(megabytes(std::size_t(2)), size);
|
||||
auto buf =
|
||||
boost::alignment::aligned_alloc(megabytes(std::size_t(2)), size);
|
||||
|
||||
// clang-format off
|
||||
if (!buf) [[unlikely]]
|
||||
@@ -229,21 +241,31 @@ public:
|
||||
|
||||
// We need to carve out a bit of memory for the slab header
|
||||
// and then align the rest appropriately:
|
||||
auto slabData = reinterpret_cast<void*>(reinterpret_cast<std::uint8_t*>(buf) + sizeof(SlabBlock));
|
||||
auto slabData = reinterpret_cast<void*>(
|
||||
reinterpret_cast<std::uint8_t*>(buf) + sizeof(SlabBlock));
|
||||
auto slabSize = size - sizeof(SlabBlock);
|
||||
|
||||
// This operation is essentially guaranteed not to fail but
|
||||
// let's be careful anyways.
|
||||
if (!boost::alignment::align(itemAlignment_, itemSize_, slabData, slabSize))
|
||||
if (!boost::alignment::align(
|
||||
itemAlignment_, itemSize_, slabData, slabSize))
|
||||
{
|
||||
boost::alignment::aligned_free(buf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
slab = new (buf) SlabBlock(slabs_.load(), reinterpret_cast<std::uint8_t*>(slabData), slabSize, itemSize_);
|
||||
slab = new (buf) SlabBlock(
|
||||
slabs_.load(),
|
||||
reinterpret_cast<std::uint8_t*>(slabData),
|
||||
slabSize,
|
||||
itemSize_);
|
||||
|
||||
// Link the new slab
|
||||
while (!slabs_.compare_exchange_weak(slab->next_, slab, std::memory_order_release, std::memory_order_relaxed))
|
||||
while (!slabs_.compare_exchange_weak(
|
||||
slab->next_,
|
||||
slab,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed))
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
@@ -300,7 +322,10 @@ public:
|
||||
std::size_t align;
|
||||
|
||||
public:
|
||||
constexpr SlabConfig(std::size_t extra_, std::size_t alloc_ = 0, std::size_t align_ = alignof(Type))
|
||||
constexpr SlabConfig(
|
||||
std::size_t extra_,
|
||||
std::size_t alloc_ = 0,
|
||||
std::size_t align_ = alignof(Type))
|
||||
: extra(extra_), alloc(alloc_), align(align_)
|
||||
{
|
||||
}
|
||||
@@ -311,14 +336,23 @@ public:
|
||||
// Ensure that the specified allocators are sorted from smallest to
|
||||
// largest by size:
|
||||
std::sort(
|
||||
std::begin(cfg), std::end(cfg), [](SlabConfig const& a, SlabConfig const& b) { return a.extra < b.extra; });
|
||||
std::begin(cfg),
|
||||
std::end(cfg),
|
||||
[](SlabConfig const& a, SlabConfig const& b) {
|
||||
return a.extra < b.extra;
|
||||
});
|
||||
|
||||
// We should never have two slabs of the same size
|
||||
if (std::adjacent_find(std::begin(cfg), std::end(cfg), [](SlabConfig const& a, SlabConfig const& b) {
|
||||
return a.extra == b.extra;
|
||||
}) != cfg.end())
|
||||
if (std::adjacent_find(
|
||||
std::begin(cfg),
|
||||
std::end(cfg),
|
||||
[](SlabConfig const& a, SlabConfig const& b) {
|
||||
return a.extra == b.extra;
|
||||
}) != cfg.end())
|
||||
{
|
||||
throw std::runtime_error("SlabAllocatorSet<" + beast::type_name<Type>() + ">: duplicate slab size");
|
||||
throw std::runtime_error(
|
||||
"SlabAllocatorSet<" + beast::type_name<Type>() +
|
||||
">: duplicate slab size");
|
||||
}
|
||||
|
||||
for (auto const& c : cfg)
|
||||
|
||||
@@ -41,7 +41,8 @@ public:
|
||||
operator=(Slice const&) noexcept = default;
|
||||
|
||||
/** Create a slice pointing to existing memory. */
|
||||
Slice(void const* data, std::size_t size) noexcept : data_(reinterpret_cast<std::uint8_t const*>(data)), size_(size)
|
||||
Slice(void const* data, std::size_t size) noexcept
|
||||
: data_(reinterpret_cast<std::uint8_t const*>(data)), size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -84,7 +85,9 @@ public:
|
||||
std::uint8_t
|
||||
operator[](std::size_t i) const noexcept
|
||||
{
|
||||
XRPL_ASSERT(i < size_, "xrpl::Slice::operator[](std::size_t) const : valid input");
|
||||
XRPL_ASSERT(
|
||||
i < size_,
|
||||
"xrpl::Slice::operator[](std::size_t) const : valid input");
|
||||
return data_[i];
|
||||
}
|
||||
|
||||
@@ -159,7 +162,9 @@ public:
|
||||
@throws std::out_of_range if pos > size()
|
||||
*/
|
||||
Slice
|
||||
substr(std::size_t pos, std::size_t count = std::numeric_limits<std::size_t>::max()) const
|
||||
substr(
|
||||
std::size_t pos,
|
||||
std::size_t count = std::numeric_limits<std::size_t>::max()) const
|
||||
{
|
||||
if (pos > size())
|
||||
throw std::out_of_range("Requested sub-slice is out of bounds");
|
||||
@@ -198,7 +203,11 @@ operator!=(Slice const& lhs, Slice const& rhs) noexcept
|
||||
inline bool
|
||||
operator<(Slice const& lhs, Slice const& rhs) noexcept
|
||||
{
|
||||
return std::lexicographical_compare(lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size());
|
||||
return std::lexicographical_compare(
|
||||
lhs.data(),
|
||||
lhs.data() + lhs.size(),
|
||||
rhs.data(),
|
||||
rhs.data() + rhs.size());
|
||||
}
|
||||
|
||||
template <class Stream>
|
||||
@@ -210,14 +219,18 @@ operator<<(Stream& s, Slice const& v)
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
std::enable_if_t<std::is_same<T, char>::value || std::is_same<T, unsigned char>::value, Slice>
|
||||
std::enable_if_t<
|
||||
std::is_same<T, char>::value || std::is_same<T, unsigned char>::value,
|
||||
Slice>
|
||||
makeSlice(std::array<T, N> const& a)
|
||||
{
|
||||
return Slice(a.data(), a.size());
|
||||
}
|
||||
|
||||
template <class T, class Alloc>
|
||||
std::enable_if_t<std::is_same<T, char>::value || std::is_same<T, unsigned char>::value, Slice>
|
||||
std::enable_if_t<
|
||||
std::is_same<T, char>::value || std::is_same<T, unsigned char>::value,
|
||||
Slice>
|
||||
makeSlice(std::vector<T, Alloc> const& v)
|
||||
{
|
||||
return Slice(v.data(), v.size());
|
||||
|
||||
@@ -109,7 +109,8 @@ struct parsedURL
|
||||
bool
|
||||
operator==(parsedURL const& other) const
|
||||
{
|
||||
return scheme == other.scheme && domain == other.domain && port == other.port && path == other.path;
|
||||
return scheme == other.scheme && domain == other.domain &&
|
||||
port == other.port && path == other.path;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ public:
|
||||
clock_type::duration expiration,
|
||||
clock_type& clock,
|
||||
beast::Journal journal,
|
||||
beast::insight::Collector::ptr const& collector = beast::insight::NullCollector::New());
|
||||
beast::insight::Collector::ptr const& collector =
|
||||
beast::insight::NullCollector::New());
|
||||
|
||||
public:
|
||||
/** Return the clock associated with the cache. */
|
||||
@@ -113,10 +114,15 @@ public:
|
||||
*/
|
||||
template <class R>
|
||||
bool
|
||||
canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback);
|
||||
canonicalize(
|
||||
key_type const& key,
|
||||
SharedPointerType& data,
|
||||
R&& replaceCallback);
|
||||
|
||||
bool
|
||||
canonicalize_replace_cache(key_type const& key, SharedPointerType const& data);
|
||||
canonicalize_replace_cache(
|
||||
key_type const& key,
|
||||
SharedPointerType const& data);
|
||||
|
||||
bool
|
||||
canonicalize_replace_client(key_type const& key, SharedPointerType& data);
|
||||
@@ -130,7 +136,8 @@ 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)
|
||||
-> std::enable_if_t<!IsKeyCache, ReturnType>;
|
||||
|
||||
template <class ReturnType = bool>
|
||||
auto
|
||||
@@ -176,7 +183,10 @@ private:
|
||||
struct Stats
|
||||
{
|
||||
template <class Handler>
|
||||
Stats(std::string const& prefix, Handler const& handler, beast::insight::Collector::ptr const& collector)
|
||||
Stats(
|
||||
std::string const& prefix,
|
||||
Handler const& handler,
|
||||
beast::insight::Collector::ptr const& collector)
|
||||
: hook(collector->make_hook(handler))
|
||||
, size(collector->make_gauge(prefix, "size"))
|
||||
, hit_rate(collector->make_gauge(prefix, "hit_rate"))
|
||||
@@ -198,7 +208,8 @@ private:
|
||||
public:
|
||||
clock_type::time_point last_access;
|
||||
|
||||
explicit KeyOnlyEntry(clock_type::time_point const& last_access_) : last_access(last_access_)
|
||||
explicit KeyOnlyEntry(clock_type::time_point const& last_access_)
|
||||
: last_access(last_access_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -215,7 +226,9 @@ private:
|
||||
shared_weak_combo_pointer_type ptr;
|
||||
clock_type::time_point last_access;
|
||||
|
||||
ValueEntry(clock_type::time_point const& last_access_, shared_pointer_type const& ptr_)
|
||||
ValueEntry(
|
||||
clock_type::time_point const& last_access_,
|
||||
shared_pointer_type const& ptr_)
|
||||
: ptr(ptr_), last_access(last_access_)
|
||||
{
|
||||
}
|
||||
@@ -249,13 +262,18 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename std::conditional<IsKeyCache, KeyOnlyEntry, ValueEntry>::type Entry;
|
||||
typedef
|
||||
typename std::conditional<IsKeyCache, KeyOnlyEntry, ValueEntry>::type
|
||||
Entry;
|
||||
|
||||
using KeyOnlyCacheType = hardened_partitioned_hash_map<key_type, KeyOnlyEntry, Hash, KeyEqual>;
|
||||
using KeyOnlyCacheType =
|
||||
hardened_partitioned_hash_map<key_type, KeyOnlyEntry, Hash, KeyEqual>;
|
||||
|
||||
using KeyValueCacheType = hardened_partitioned_hash_map<key_type, ValueEntry, Hash, KeyEqual>;
|
||||
using KeyValueCacheType =
|
||||
hardened_partitioned_hash_map<key_type, ValueEntry, Hash, KeyEqual>;
|
||||
|
||||
using cache_type = hardened_partitioned_hash_map<key_type, Entry, Hash, KeyEqual>;
|
||||
using cache_type =
|
||||
hardened_partitioned_hash_map<key_type, Entry, Hash, KeyEqual>;
|
||||
|
||||
[[nodiscard]] std::thread
|
||||
sweepHelper(
|
||||
|
||||
@@ -15,13 +15,22 @@ template <
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::TaggedCache(
|
||||
std::string const& name,
|
||||
int size,
|
||||
clock_type::duration expiration,
|
||||
clock_type& clock,
|
||||
beast::Journal journal,
|
||||
beast::insight::Collector::ptr const& collector)
|
||||
inline TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
TaggedCache(
|
||||
std::string const& name,
|
||||
int size,
|
||||
clock_type::duration expiration,
|
||||
clock_type& clock,
|
||||
beast::Journal journal,
|
||||
beast::insight::Collector::ptr const& collector)
|
||||
: m_journal(journal)
|
||||
, m_clock(clock)
|
||||
, m_stats(name, std::bind(&TaggedCache::collect_metrics, this), collector)
|
||||
@@ -44,8 +53,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline auto
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::clock()
|
||||
-> clock_type&
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::clock() -> clock_type&
|
||||
{
|
||||
return m_clock;
|
||||
}
|
||||
@@ -60,7 +76,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline std::size_t
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::size() const
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::size() const
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
return m_cache.size();
|
||||
@@ -76,7 +100,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline int
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::getCacheSize() const
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::getCacheSize() const
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
return m_cache_count;
|
||||
@@ -92,7 +124,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline int
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::getTrackSize() const
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::getTrackSize() const
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
return m_cache.size();
|
||||
@@ -108,7 +148,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline float
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::getHitRate()
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::getHitRate()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
auto const total = static_cast<float>(m_hits + m_misses);
|
||||
@@ -125,7 +173,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline void
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::clear()
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::clear()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
m_cache.clear();
|
||||
@@ -142,7 +198,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline void
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::reset()
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::reset()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
m_cache.clear();
|
||||
@@ -162,8 +226,15 @@ template <
|
||||
class Mutex>
|
||||
template <class KeyComparable>
|
||||
inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::touch_if_exists(
|
||||
KeyComparable const& key)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::touch_if_exists(KeyComparable const& key)
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
auto const iter(m_cache.find(key));
|
||||
@@ -187,7 +258,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline void
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::sweep()
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::sweep()
|
||||
{
|
||||
// Keep references to all the stuff we sweep
|
||||
// For performance, each worker thread should exit before the swept data
|
||||
@@ -201,7 +280,8 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
if (m_target_size == 0 || (static_cast<int>(m_cache.size()) <= m_target_size))
|
||||
if (m_target_size == 0 ||
|
||||
(static_cast<int>(m_cache.size()) <= m_target_size))
|
||||
{
|
||||
when_expire = now - m_target_age;
|
||||
}
|
||||
@@ -213,8 +293,10 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
if (when_expire > (now - minimumAge))
|
||||
when_expire = now - minimumAge;
|
||||
|
||||
JLOG(m_journal.trace()) << m_name << " is growing fast " << m_cache.size() << " of " << m_target_size
|
||||
<< " aging at " << (now - when_expire).count() << " of " << m_target_age.count();
|
||||
JLOG(m_journal.trace())
|
||||
<< m_name << " is growing fast " << m_cache.size() << " of "
|
||||
<< m_target_size << " aging at " << (now - when_expire).count()
|
||||
<< " of " << m_target_age.count();
|
||||
}
|
||||
|
||||
std::vector<std::thread> workers;
|
||||
@@ -223,7 +305,13 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
|
||||
for (std::size_t p = 0; p < m_cache.partitions(); ++p)
|
||||
{
|
||||
workers.push_back(sweepHelper(when_expire, now, m_cache.map()[p], allStuffToSweep[p], allRemovals, lock));
|
||||
workers.push_back(sweepHelper(
|
||||
when_expire,
|
||||
now,
|
||||
m_cache.map()[p],
|
||||
allStuffToSweep[p],
|
||||
allRemovals,
|
||||
lock));
|
||||
}
|
||||
for (std::thread& worker : workers)
|
||||
worker.join();
|
||||
@@ -234,7 +322,9 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
// and decrement the reference count on each strong pointer.
|
||||
JLOG(m_journal.debug())
|
||||
<< m_name << " TaggedCache sweep lock duration "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count()
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count()
|
||||
<< "ms";
|
||||
}
|
||||
|
||||
@@ -248,9 +338,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::del(
|
||||
key_type const& key,
|
||||
bool valid)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::del(key_type const& key, bool valid)
|
||||
{
|
||||
// Remove from cache, if !valid, remove from map too. Returns true if
|
||||
// removed from cache
|
||||
@@ -289,10 +385,19 @@ template <
|
||||
class Mutex>
|
||||
template <class R>
|
||||
inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::canonicalize(
|
||||
key_type const& key,
|
||||
SharedPointerType& data,
|
||||
R&& replaceCallback)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
canonicalize(
|
||||
key_type const& key,
|
||||
SharedPointerType& data,
|
||||
R&& replaceCallback)
|
||||
{
|
||||
// Return canonical value, store if needed, refresh in cache
|
||||
// Return values: true=we had the data already
|
||||
@@ -303,7 +408,9 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
if (cit == m_cache.end())
|
||||
{
|
||||
m_cache.emplace(
|
||||
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(m_clock.now(), data));
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(key),
|
||||
std::forward_as_tuple(m_clock.now(), data));
|
||||
++m_cache_count;
|
||||
return false;
|
||||
}
|
||||
@@ -373,10 +480,21 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
|
||||
canonicalize_replace_cache(key_type const& key, SharedPointerType const& data)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
canonicalize_replace_cache(
|
||||
key_type const& key,
|
||||
SharedPointerType const& data)
|
||||
{
|
||||
return canonicalize(key, const_cast<SharedPointerType&>(data), []() { return true; });
|
||||
return canonicalize(
|
||||
key, const_cast<SharedPointerType&>(data), []() { return true; });
|
||||
}
|
||||
|
||||
template <
|
||||
@@ -389,7 +507,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
canonicalize_replace_client(key_type const& key, SharedPointerType& data)
|
||||
{
|
||||
return canonicalize(key, data, []() { return false; });
|
||||
@@ -405,8 +531,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline SharedPointerType
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::fetch(
|
||||
key_type const& key)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::fetch(key_type const& key)
|
||||
{
|
||||
std::lock_guard<mutex_type> l(m_mutex);
|
||||
auto ret = initialFetch(key, l);
|
||||
@@ -426,9 +559,16 @@ template <
|
||||
class Mutex>
|
||||
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>
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::insert(key_type const& key, T const& value)
|
||||
-> std::enable_if_t<!IsKeyCache, ReturnType>
|
||||
{
|
||||
static_assert(
|
||||
std::is_same_v<std::shared_ptr<T>, SharedPointerType> ||
|
||||
@@ -457,13 +597,23 @@ template <
|
||||
class Mutex>
|
||||
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>
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::insert(key_type const& key)
|
||||
-> std::enable_if_t<IsKeyCache, ReturnType>
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
clock_type::time_point const now(m_clock.now());
|
||||
auto [it, inserted] =
|
||||
m_cache.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now));
|
||||
auto [it, inserted] = m_cache.emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(key),
|
||||
std::forward_as_tuple(now));
|
||||
if (!inserted)
|
||||
it->second.last_access = now;
|
||||
return inserted;
|
||||
@@ -479,9 +629,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline bool
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::retrieve(
|
||||
key_type const& key,
|
||||
T& data)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::retrieve(key_type const& key, T& data)
|
||||
{
|
||||
// retrieve the value of the stored data
|
||||
auto entry = fetch(key);
|
||||
@@ -503,8 +659,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline auto
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::peekMutex()
|
||||
-> mutex_type&
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::peekMutex() -> mutex_type&
|
||||
{
|
||||
return m_mutex;
|
||||
}
|
||||
@@ -519,8 +682,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline auto
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::getKeys() const
|
||||
-> std::vector<key_type>
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::getKeys() const -> std::vector<key_type>
|
||||
{
|
||||
std::vector<key_type> v;
|
||||
|
||||
@@ -544,7 +714,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline double
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::rate() const
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::rate() const
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
auto const tot = m_hits + m_misses;
|
||||
@@ -564,9 +742,15 @@ template <
|
||||
class Mutex>
|
||||
template <class Handler>
|
||||
inline SharedPointerType
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::fetch(
|
||||
key_type const& digest,
|
||||
Handler const& h)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::fetch(key_type const& digest, Handler const& h)
|
||||
{
|
||||
{
|
||||
std::lock_guard l(m_mutex);
|
||||
@@ -580,7 +764,8 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
|
||||
std::lock_guard l(m_mutex);
|
||||
++m_misses;
|
||||
auto const [it, inserted] = m_cache.emplace(digest, Entry(m_clock.now(), std::move(sle)));
|
||||
auto const [it, inserted] =
|
||||
m_cache.emplace(digest, Entry(m_clock.now(), std::move(sle)));
|
||||
if (!inserted)
|
||||
it->second.touch(m_clock.now());
|
||||
return it->second.ptr.getStrong();
|
||||
@@ -597,9 +782,16 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline SharedPointerType
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::initialFetch(
|
||||
key_type const& key,
|
||||
std::lock_guard<mutex_type> const& l)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
initialFetch(key_type const& key, std::lock_guard<mutex_type> const& l)
|
||||
{
|
||||
auto cit = m_cache.find(key);
|
||||
if (cit == m_cache.end())
|
||||
@@ -635,7 +827,15 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline void
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::collect_metrics()
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::collect_metrics()
|
||||
{
|
||||
m_stats.size.set(getCacheSize());
|
||||
|
||||
@@ -661,13 +861,22 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline std::thread
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::sweepHelper(
|
||||
clock_type::time_point const& when_expire,
|
||||
[[maybe_unused]] clock_type::time_point const& now,
|
||||
typename KeyValueCacheType::map_type& partition,
|
||||
SweptPointersVector& stuffToSweep,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::lock_guard<std::recursive_mutex> const&)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
sweepHelper(
|
||||
clock_type::time_point const& when_expire,
|
||||
[[maybe_unused]] clock_type::time_point const& now,
|
||||
typename KeyValueCacheType::map_type& partition,
|
||||
SweptPointersVector& stuffToSweep,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::lock_guard<std::recursive_mutex> const&)
|
||||
{
|
||||
return std::thread([&, this]() {
|
||||
int cacheRemovals = 0;
|
||||
@@ -721,8 +930,10 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
|
||||
if (mapRemovals || cacheRemovals)
|
||||
{
|
||||
JLOG(m_journal.debug()) << "TaggedCache partition sweep " << m_name << ": cache = " << partition.size()
|
||||
<< "-" << cacheRemovals << ", map-=" << mapRemovals;
|
||||
JLOG(m_journal.debug())
|
||||
<< "TaggedCache partition sweep " << m_name
|
||||
<< ": cache = " << partition.size() << "-" << cacheRemovals
|
||||
<< ", map-=" << mapRemovals;
|
||||
}
|
||||
|
||||
allRemovals += cacheRemovals;
|
||||
@@ -739,13 +950,22 @@ template <
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
inline std::thread
|
||||
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::sweepHelper(
|
||||
clock_type::time_point const& when_expire,
|
||||
clock_type::time_point const& now,
|
||||
typename KeyOnlyCacheType::map_type& partition,
|
||||
SweptPointersVector&,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::lock_guard<std::recursive_mutex> const&)
|
||||
TaggedCache<
|
||||
Key,
|
||||
T,
|
||||
IsKeyCache,
|
||||
SharedWeakUnionPointer,
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
sweepHelper(
|
||||
clock_type::time_point const& when_expire,
|
||||
clock_type::time_point const& now,
|
||||
typename KeyOnlyCacheType::map_type& partition,
|
||||
SweptPointersVector&,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::lock_guard<std::recursive_mutex> const&)
|
||||
{
|
||||
return std::thread([&, this]() {
|
||||
int cacheRemovals = 0;
|
||||
@@ -775,8 +995,10 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
|
||||
if (mapRemovals || cacheRemovals)
|
||||
{
|
||||
JLOG(m_journal.debug()) << "TaggedCache partition sweep " << m_name << ": cache = " << partition.size()
|
||||
<< "-" << cacheRemovals << ", map-=" << mapRemovals;
|
||||
JLOG(m_journal.debug())
|
||||
<< "TaggedCache partition sweep " << m_name
|
||||
<< ": cache = " << partition.size() << "-" << cacheRemovals
|
||||
<< ", map-=" << mapRemovals;
|
||||
}
|
||||
|
||||
allRemovals += cacheRemovals;
|
||||
|
||||
@@ -40,7 +40,8 @@ template <
|
||||
class Hash = beast::uhash<>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key const, Value>>>
|
||||
using hash_multimap = std::unordered_multimap<Key, Value, Hash, Pred, Allocator>;
|
||||
using hash_multimap =
|
||||
std::unordered_multimap<Key, Value, Hash, Pred, Allocator>;
|
||||
|
||||
template <
|
||||
class Value,
|
||||
@@ -74,7 +75,8 @@ template <
|
||||
class Hash = hardened_hash<strong_hash>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key const, Value>>>
|
||||
using hardened_partitioned_hash_map = partitioned_unordered_map<Key, Value, Hash, Pred, Allocator>;
|
||||
using hardened_partitioned_hash_map =
|
||||
partitioned_unordered_map<Key, Value, Hash, Pred, Allocator>;
|
||||
|
||||
template <
|
||||
class Key,
|
||||
@@ -82,7 +84,8 @@ template <
|
||||
class Hash = hardened_hash<strong_hash>,
|
||||
class Pred = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key const, Value>>>
|
||||
using hardened_hash_multimap = std::unordered_multimap<Key, Value, Hash, Pred, Allocator>;
|
||||
using hardened_hash_multimap =
|
||||
std::unordered_multimap<Key, Value, Hash, Pred, Allocator>;
|
||||
|
||||
template <
|
||||
class Value,
|
||||
@@ -96,7 +99,8 @@ template <
|
||||
class Hash = hardened_hash<strong_hash>,
|
||||
class Pred = std::equal_to<Value>,
|
||||
class Allocator = std::allocator<Value>>
|
||||
using hardened_hash_multiset = std::unordered_multiset<Value, Hash, Pred, Allocator>;
|
||||
using hardened_hash_multiset =
|
||||
std::unordered_multiset<Value, Hash, Pred, Allocator>;
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
|
||||
@@ -52,7 +52,13 @@ generalized_set_intersection(
|
||||
// std::set_intersection.
|
||||
template <class FwdIter1, class InputIter2, class Pred, class Comp>
|
||||
FwdIter1
|
||||
remove_if_intersect_or_match(FwdIter1 first1, FwdIter1 last1, InputIter2 first2, InputIter2 last2, Pred pred, Comp comp)
|
||||
remove_if_intersect_or_match(
|
||||
FwdIter1 first1,
|
||||
FwdIter1 last1,
|
||||
InputIter2 first2,
|
||||
InputIter2 last2,
|
||||
Pred pred,
|
||||
Comp comp)
|
||||
{
|
||||
// [original-first1, current-first1) is the set of elements to be preserved.
|
||||
// [current-first1, i) is the set of elements that have been removed.
|
||||
|
||||
@@ -46,7 +46,8 @@ base64_encode(std::uint8_t const* data, std::size_t len);
|
||||
inline std::string
|
||||
base64_encode(std::string const& s)
|
||||
{
|
||||
return base64_encode(reinterpret_cast<std::uint8_t const*>(s.data()), s.size());
|
||||
return base64_encode(
|
||||
reinterpret_cast<std::uint8_t const*>(s.data()), s.size());
|
||||
}
|
||||
|
||||
std::string
|
||||
|
||||
@@ -65,9 +65,13 @@ struct is_contiguous_container<Slice> : std::true_type
|
||||
template <std::size_t Bits, class Tag = void>
|
||||
class base_uint
|
||||
{
|
||||
static_assert((Bits % 32) == 0, "The length of a base_uint in bits must be a multiple of 32.");
|
||||
static_assert(
|
||||
(Bits % 32) == 0,
|
||||
"The length of a base_uint in bits must be a multiple of 32.");
|
||||
|
||||
static_assert(Bits >= 64, "The length of a base_uint in bits must be at least 64.");
|
||||
static_assert(
|
||||
Bits >= 64,
|
||||
"The length of a base_uint in bits must be at least 64.");
|
||||
|
||||
static constexpr std::size_t WIDTH = Bits / 32;
|
||||
|
||||
@@ -178,7 +182,9 @@ private:
|
||||
{
|
||||
// Local lambda that converts a single hex char to four bits and
|
||||
// ORs those bits into a uint32_t.
|
||||
auto hexCharToUInt = [](char c, std::uint32_t shift, std::uint32_t& accum) -> ParseResult {
|
||||
auto hexCharToUInt = [](char c,
|
||||
std::uint32_t shift,
|
||||
std::uint32_t& accum) -> ParseResult {
|
||||
std::uint32_t nibble = 0xFFu;
|
||||
if (c < '0' || c > 'f')
|
||||
return ParseResult::badChar;
|
||||
@@ -215,7 +221,8 @@ private:
|
||||
std::uint32_t accum = {};
|
||||
for (std::uint32_t shift : {4u, 0u, 12u, 8u, 20u, 16u, 28u, 24u})
|
||||
{
|
||||
if (auto const result = hexCharToUInt(*in++, shift, accum); result != ParseResult::okay)
|
||||
if (auto const result = hexCharToUInt(*in++, shift, accum);
|
||||
result != ParseResult::okay)
|
||||
return Unexpected(result);
|
||||
}
|
||||
ret[i++] = accum;
|
||||
@@ -254,7 +261,8 @@ public:
|
||||
// This constructor is intended to be used at compile time since it might
|
||||
// throw at runtime. Consider declaring this constructor consteval once
|
||||
// we get to C++23.
|
||||
explicit constexpr base_uint(std::string_view sv) noexcept(false) : data_(parseFromStringViewThrows(sv))
|
||||
explicit constexpr base_uint(std::string_view sv) noexcept(false)
|
||||
: data_(parseFromStringViewThrows(sv))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -379,7 +387,8 @@ public:
|
||||
// prefix operator
|
||||
for (int i = WIDTH - 1; i >= 0; --i)
|
||||
{
|
||||
data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) + 1);
|
||||
data_[i] = boost::endian::native_to_big(
|
||||
boost::endian::big_to_native(data_[i]) + 1);
|
||||
if (data_[i] != 0)
|
||||
break;
|
||||
}
|
||||
@@ -403,7 +412,8 @@ public:
|
||||
for (int i = WIDTH - 1; i >= 0; --i)
|
||||
{
|
||||
auto prev = data_[i];
|
||||
data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) - 1);
|
||||
data_[i] = boost::endian::native_to_big(
|
||||
boost::endian::big_to_native(data_[i]) - 1);
|
||||
|
||||
if (prev != 0)
|
||||
break;
|
||||
@@ -443,9 +453,11 @@ public:
|
||||
|
||||
for (int i = WIDTH; i--;)
|
||||
{
|
||||
std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) + boost::endian::big_to_native(b.data_[i]);
|
||||
std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) +
|
||||
boost::endian::big_to_native(b.data_[i]);
|
||||
|
||||
data_[i] = boost::endian::native_to_big(static_cast<std::uint32_t>(n));
|
||||
data_[i] =
|
||||
boost::endian::native_to_big(static_cast<std::uint32_t>(n));
|
||||
carry = n >> 32;
|
||||
}
|
||||
|
||||
@@ -545,7 +557,8 @@ operator<=>(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
|
||||
if (ret.first == lhs.cend())
|
||||
return std::strong_ordering::equivalent;
|
||||
|
||||
return (*ret.first > *ret.second) ? std::strong_ordering::greater : std::strong_ordering::less;
|
||||
return (*ret.first > *ret.second) ? std::strong_ordering::greater
|
||||
: std::strong_ordering::less;
|
||||
}
|
||||
|
||||
template <std::size_t Bits, typename Tag>
|
||||
@@ -604,7 +617,9 @@ template <std::size_t Bits, class Tag>
|
||||
inline std::string
|
||||
to_short_string(base_uint<Bits, Tag> const& a)
|
||||
{
|
||||
static_assert(base_uint<Bits, Tag>::bytes > 4, "For 4 bytes or less, use a native type");
|
||||
static_assert(
|
||||
base_uint<Bits, Tag>::bytes > 4,
|
||||
"For 4 bytes or less, use a native type");
|
||||
return strHex(a.cbegin(), a.cbegin() + 4) + "...";
|
||||
}
|
||||
|
||||
@@ -638,7 +653,8 @@ static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
|
||||
namespace beast {
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
struct is_uniquely_represented<xrpl::base_uint<Bits, Tag>> : public std::true_type
|
||||
struct is_uniquely_represented<xrpl::base_uint<Bits, Tag>>
|
||||
: public std::true_type
|
||||
{
|
||||
explicit is_uniquely_represented() = default;
|
||||
};
|
||||
|
||||
@@ -16,9 +16,12 @@ namespace xrpl {
|
||||
|
||||
// A few handy aliases
|
||||
|
||||
using days = std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>>;
|
||||
using days = std::chrono::duration<
|
||||
int,
|
||||
std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>>;
|
||||
|
||||
using weeks = std::chrono::duration<int, std::ratio_multiply<days::period, std::ratio<7>>>;
|
||||
using weeks = std::chrono::
|
||||
duration<int, std::ratio_multiply<days::period, std::ratio<7>>>;
|
||||
|
||||
/** Clock for measuring the network time.
|
||||
|
||||
@@ -31,7 +34,8 @@ using weeks = std::chrono::duration<int, std::ratio_multiply<days::period, std::
|
||||
*/
|
||||
|
||||
constexpr static std::chrono::seconds epoch_offset =
|
||||
date::sys_days{date::year{2000} / 1 / 1} - date::sys_days{date::year{1970} / 1 / 1};
|
||||
date::sys_days{date::year{2000} / 1 / 1} -
|
||||
date::sys_days{date::year{1970} / 1 / 1};
|
||||
|
||||
static_assert(epoch_offset.count() == 946684800);
|
||||
|
||||
@@ -60,7 +64,8 @@ to_string(NetClock::time_point tp)
|
||||
{
|
||||
// 2000-01-01 00:00:00 UTC is 946684800s from 1970-01-01 00:00:00 UTC
|
||||
using namespace std::chrono;
|
||||
return to_string(system_clock::time_point{tp.time_since_epoch() + epoch_offset});
|
||||
return to_string(
|
||||
system_clock::time_point{tp.time_since_epoch() + epoch_offset});
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
@@ -77,7 +82,8 @@ to_string_iso(NetClock::time_point tp)
|
||||
// 2000-01-01 00:00:00 UTC is 946684800s from 1970-01-01 00:00:00 UTC
|
||||
// Note, NetClock::duration is seconds, as checked by static_assert
|
||||
static_assert(std::is_same_v<NetClock::duration::period, std::ratio<1>>);
|
||||
return to_string_iso(date::sys_time<NetClock::duration>{tp.time_since_epoch() + epoch_offset});
|
||||
return to_string_iso(date::sys_time<NetClock::duration>{
|
||||
tp.time_since_epoch() + epoch_offset});
|
||||
}
|
||||
|
||||
/** A clock for measuring elapsed time.
|
||||
|
||||
@@ -36,10 +36,15 @@ template <class E, class... Args>
|
||||
[[noreturn]] inline void
|
||||
Throw(Args&&... args)
|
||||
{
|
||||
static_assert(std::is_convertible<E*, std::exception*>::value, "Exception must derive from std::exception.");
|
||||
static_assert(
|
||||
std::is_convertible<E*, std::exception*>::value,
|
||||
"Exception must derive from std::exception.");
|
||||
|
||||
E e(std::forward<Args>(args)...);
|
||||
LogThrow(std::string("Throwing exception of type " + beast::type_name<E>() + ": ") + e.what());
|
||||
LogThrow(
|
||||
std::string(
|
||||
"Throwing exception of type " + beast::type_name<E>() + ": ") +
|
||||
e.what());
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ public:
|
||||
Collection const& collection;
|
||||
std::string const delimiter;
|
||||
|
||||
explicit CollectionAndDelimiter(Collection const& c, std::string delim) : collection(c), delimiter(std::move(delim))
|
||||
explicit CollectionAndDelimiter(Collection const& c, std::string delim)
|
||||
: collection(c), delimiter(std::move(delim))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -32,7 +33,11 @@ public:
|
||||
friend Stream&
|
||||
operator<<(Stream& s, CollectionAndDelimiter const& cd)
|
||||
{
|
||||
return join(s, std::begin(cd.collection), std::end(cd.collection), cd.delimiter);
|
||||
return join(
|
||||
s,
|
||||
std::begin(cd.collection),
|
||||
std::end(cd.collection),
|
||||
cd.delimiter);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,7 +69,8 @@ public:
|
||||
char const* collection;
|
||||
std::string const delimiter;
|
||||
|
||||
explicit CollectionAndDelimiter(char const c[N], std::string delim) : collection(c), delimiter(std::move(delim))
|
||||
explicit CollectionAndDelimiter(char const c[N], std::string delim)
|
||||
: collection(c), delimiter(std::move(delim))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ public:
|
||||
using const_reference = value_type const&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = value_type const*;
|
||||
using map_type = std::unordered_map<key_type, mapped_type, hasher, key_equal, allocator_type>;
|
||||
using map_type = std::
|
||||
unordered_map<key_type, mapped_type, hasher, key_equal, allocator_type>;
|
||||
using partition_map_type = std::vector<map_type>;
|
||||
|
||||
struct iterator
|
||||
@@ -112,7 +113,8 @@ public:
|
||||
friend bool
|
||||
operator==(iterator const& lhs, iterator const& rhs)
|
||||
{
|
||||
return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ && lhs.mit_ == rhs.mit_;
|
||||
return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ &&
|
||||
lhs.mit_ == rhs.mit_;
|
||||
}
|
||||
|
||||
friend bool
|
||||
@@ -188,7 +190,8 @@ public:
|
||||
friend bool
|
||||
operator==(const_iterator const& lhs, const_iterator const& rhs)
|
||||
{
|
||||
return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ && lhs.mit_ == rhs.mit_;
|
||||
return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ &&
|
||||
lhs.mit_ == rhs.mit_;
|
||||
}
|
||||
|
||||
friend bool
|
||||
@@ -228,11 +231,14 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
partitioned_unordered_map(std::optional<std::size_t> partitions = std::nullopt)
|
||||
partitioned_unordered_map(
|
||||
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 ? *partitions : std::thread::hardware_concurrency();
|
||||
partitions_ = partitions && *partitions
|
||||
? *partitions
|
||||
: std::thread::hardware_concurrency();
|
||||
map_.resize(partitions_);
|
||||
XRPL_ASSERT(
|
||||
partitions_,
|
||||
@@ -331,8 +337,10 @@ public:
|
||||
auto const& key = std::get<0>(keyTuple);
|
||||
iterator it(&map_);
|
||||
it.ait_ = it.map_->begin() + partitioner(key);
|
||||
auto [eit, inserted] =
|
||||
it.ait_->emplace(std::piecewise_construct, std::forward<T>(keyTuple), std::forward<U>(valueTuple));
|
||||
auto [eit, inserted] = it.ait_->emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward<T>(keyTuple),
|
||||
std::forward<U>(valueTuple));
|
||||
it.mit_ = eit;
|
||||
return {it, inserted};
|
||||
}
|
||||
@@ -343,7 +351,8 @@ public:
|
||||
{
|
||||
iterator it(&map_);
|
||||
it.ait_ = it.map_->begin() + partitioner(key);
|
||||
auto [eit, inserted] = it.ait_->emplace(std::forward<T>(key), std::forward<U>(val));
|
||||
auto [eit, inserted] =
|
||||
it.ait_->emplace(std::forward<T>(key), std::forward<U>(val));
|
||||
it.mit_ = eit;
|
||||
return {it, inserted};
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ static_assert(
|
||||
"The Ripple default PRNG engine must return an unsigned integral type.");
|
||||
|
||||
static_assert(
|
||||
std::numeric_limits<beast::xor_shift_engine::result_type>::max() >= std::numeric_limits<std::uint64_t>::max(),
|
||||
std::numeric_limits<beast::xor_shift_engine::result_type>::max() >=
|
||||
std::numeric_limits<std::uint64_t>::max(),
|
||||
"The Ripple default PRNG engine return must be at least 64 bits wide.");
|
||||
#endif
|
||||
|
||||
@@ -89,7 +90,9 @@ default_prng()
|
||||
*/
|
||||
/** @{ */
|
||||
template <class Engine, class Integral>
|
||||
std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
|
||||
std::enable_if_t<
|
||||
std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
|
||||
Integral>
|
||||
rand_int(Engine& engine, Integral min, Integral max)
|
||||
{
|
||||
XRPL_ASSERT(max > min, "xrpl::rand_int : max over min inputs");
|
||||
@@ -108,7 +111,9 @@ rand_int(Integral min, Integral max)
|
||||
}
|
||||
|
||||
template <class Engine, class Integral>
|
||||
std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
|
||||
std::enable_if_t<
|
||||
std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
|
||||
Integral>
|
||||
rand_int(Engine& engine, Integral max)
|
||||
{
|
||||
return rand_int(engine, Integral(0), max);
|
||||
@@ -122,7 +127,9 @@ rand_int(Integral max)
|
||||
}
|
||||
|
||||
template <class Integral, class Engine>
|
||||
std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
|
||||
std::enable_if_t<
|
||||
std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
|
||||
Integral>
|
||||
rand_int(Engine& engine)
|
||||
{
|
||||
return rand_int(engine, std::numeric_limits<Integral>::max());
|
||||
@@ -140,17 +147,23 @@ rand_int()
|
||||
/** @{ */
|
||||
template <class Byte, class Engine>
|
||||
std::enable_if_t<
|
||||
(std::is_same<Byte, unsigned char>::value || std::is_same<Byte, std::uint8_t>::value) &&
|
||||
(std::is_same<Byte, unsigned char>::value ||
|
||||
std::is_same<Byte, std::uint8_t>::value) &&
|
||||
detail::is_engine<Engine>::value,
|
||||
Byte>
|
||||
rand_byte(Engine& engine)
|
||||
{
|
||||
return static_cast<Byte>(
|
||||
rand_int<Engine, std::uint32_t>(engine, std::numeric_limits<Byte>::min(), std::numeric_limits<Byte>::max()));
|
||||
return static_cast<Byte>(rand_int<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<Byte, unsigned char>::value || std::is_same<Byte, std::uint8_t>::value), Byte>
|
||||
std::enable_if_t<
|
||||
(std::is_same<Byte, unsigned char>::value ||
|
||||
std::is_same<Byte, std::uint8_t>::value),
|
||||
Byte>
|
||||
rand_byte()
|
||||
{
|
||||
return rand_byte<Byte>(default_prng());
|
||||
|
||||
@@ -12,29 +12,38 @@ namespace xrpl {
|
||||
template <class Src, class Dest>
|
||||
concept SafeToCast = (std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
|
||||
(std::is_signed<Src>::value || std::is_unsigned<Dest>::value) &&
|
||||
(std::is_signed<Src>::value != std::is_signed<Dest>::value ? sizeof(Dest) > sizeof(Src)
|
||||
: sizeof(Dest) >= sizeof(Src));
|
||||
(std::is_signed<Src>::value != std::is_signed<Dest>::value
|
||||
? sizeof(Dest) > sizeof(Src)
|
||||
: sizeof(Dest) >= sizeof(Src));
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
safe_cast(Src s) noexcept
|
||||
inline constexpr std::
|
||||
enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
safe_cast(Src s) noexcept
|
||||
{
|
||||
static_assert(std::is_signed_v<Dest> || std::is_unsigned_v<Src>, "Cannot cast signed to unsigned");
|
||||
constexpr unsigned not_same = std::is_signed_v<Dest> != std::is_signed_v<Src>;
|
||||
static_assert(sizeof(Dest) >= sizeof(Src) + not_same, "Destination is too small to hold all values of source");
|
||||
static_assert(
|
||||
std::is_signed_v<Dest> || std::is_unsigned_v<Src>,
|
||||
"Cannot cast signed to unsigned");
|
||||
constexpr unsigned not_same =
|
||||
std::is_signed_v<Dest> != std::is_signed_v<Src>;
|
||||
static_assert(
|
||||
sizeof(Dest) >= sizeof(Src) + not_same,
|
||||
"Destination is too small to hold all values of source");
|
||||
return static_cast<Dest>(s);
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
safe_cast(Src s) noexcept
|
||||
inline constexpr std::
|
||||
enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
safe_cast(Src s) noexcept
|
||||
{
|
||||
return static_cast<Dest>(safe_cast<std::underlying_type_t<Dest>>(s));
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
|
||||
safe_cast(Src s) noexcept
|
||||
inline constexpr std::
|
||||
enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
|
||||
safe_cast(Src s) noexcept
|
||||
{
|
||||
return safe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
|
||||
}
|
||||
@@ -44,8 +53,9 @@ safe_cast(Src s) noexcept
|
||||
// underlying types become safe, it can be converted to a safe_cast.
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
unsafe_cast(Src s) noexcept
|
||||
inline constexpr std::
|
||||
enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
unsafe_cast(Src s) noexcept
|
||||
{
|
||||
static_assert(
|
||||
!SafeToCast<Src, Dest>,
|
||||
@@ -55,15 +65,17 @@ unsafe_cast(Src s) noexcept
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
unsafe_cast(Src s) noexcept
|
||||
inline constexpr std::
|
||||
enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
|
||||
unsafe_cast(Src s) noexcept
|
||||
{
|
||||
return static_cast<Dest>(unsafe_cast<std::underlying_type_t<Dest>>(s));
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
|
||||
unsafe_cast(Src s) noexcept
|
||||
inline constexpr std::
|
||||
enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
|
||||
unsafe_cast(Src s) noexcept
|
||||
{
|
||||
return unsafe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
|
||||
}
|
||||
|
||||
@@ -36,8 +36,10 @@ public:
|
||||
}
|
||||
|
||||
scope_exit(scope_exit&& 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_}
|
||||
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_}
|
||||
{
|
||||
rhs.release();
|
||||
}
|
||||
@@ -48,11 +50,14 @@ public:
|
||||
template <class EFP>
|
||||
explicit scope_exit(
|
||||
EFP&& f,
|
||||
std::enable_if_t<!std::is_same_v<std::remove_cv_t<EFP>, scope_exit> && std::is_constructible_v<EF, EFP>>* =
|
||||
0) noexcept
|
||||
std::enable_if_t<
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, scope_exit> &&
|
||||
std::is_constructible_v<EF, EFP>>* = 0) noexcept
|
||||
: exit_function_{std::forward<EFP>(f)}
|
||||
{
|
||||
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
|
||||
static_assert(
|
||||
std::
|
||||
is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -75,12 +80,14 @@ class scope_fail
|
||||
public:
|
||||
~scope_fail()
|
||||
{
|
||||
if (execute_on_destruction_ && std::uncaught_exceptions() > uncaught_on_creation_)
|
||||
if (execute_on_destruction_ &&
|
||||
std::uncaught_exceptions() > uncaught_on_creation_)
|
||||
exit_function_();
|
||||
}
|
||||
|
||||
scope_fail(scope_fail&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
|
||||
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_}
|
||||
@@ -94,11 +101,14 @@ public:
|
||||
template <class EFP>
|
||||
explicit scope_fail(
|
||||
EFP&& f,
|
||||
std::enable_if_t<!std::is_same_v<std::remove_cv_t<EFP>, scope_fail> && std::is_constructible_v<EF, EFP>>* =
|
||||
0) noexcept
|
||||
std::enable_if_t<
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, scope_fail> &&
|
||||
std::is_constructible_v<EF, EFP>>* = 0) noexcept
|
||||
: exit_function_{std::forward<EFP>(f)}
|
||||
{
|
||||
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
|
||||
static_assert(
|
||||
std::
|
||||
is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -121,12 +131,14 @@ class scope_success
|
||||
public:
|
||||
~scope_success() noexcept(noexcept(exit_function_()))
|
||||
{
|
||||
if (execute_on_destruction_ && std::uncaught_exceptions() <= uncaught_on_creation_)
|
||||
if (execute_on_destruction_ &&
|
||||
std::uncaught_exceptions() <= uncaught_on_creation_)
|
||||
exit_function_();
|
||||
}
|
||||
|
||||
scope_success(scope_success&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
|
||||
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_}
|
||||
@@ -140,7 +152,9 @@ public:
|
||||
template <class EFP>
|
||||
explicit scope_success(
|
||||
EFP&& f,
|
||||
std::enable_if_t<!std::is_same_v<std::remove_cv_t<EFP>, scope_success> && std::is_constructible_v<EF, EFP>>* =
|
||||
std::enable_if_t<
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, scope_success> &&
|
||||
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)}
|
||||
{
|
||||
@@ -199,9 +213,12 @@ class scope_unlock
|
||||
std::unique_lock<Mutex>* plock;
|
||||
|
||||
public:
|
||||
explicit scope_unlock(std::unique_lock<Mutex>& lock) noexcept(true) : plock(&lock)
|
||||
explicit scope_unlock(std::unique_lock<Mutex>& lock) noexcept(true)
|
||||
: plock(&lock)
|
||||
{
|
||||
XRPL_ASSERT(plock->owns_lock(), "xrpl::scope_unlock::scope_unlock : mutex must be locked");
|
||||
XRPL_ASSERT(
|
||||
plock->owns_lock(),
|
||||
"xrpl::scope_unlock::scope_unlock : mutex must be locked");
|
||||
plock->unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -100,9 +100,12 @@ public:
|
||||
@note For performance reasons, you should strive to have `lock` be
|
||||
on a cacheline by itself.
|
||||
*/
|
||||
packed_spinlock(std::atomic<T>& lock, int index) : bits_(lock), mask_(static_cast<T>(1) << index)
|
||||
packed_spinlock(std::atomic<T>& lock, int index)
|
||||
: bits_(lock), mask_(static_cast<T>(1) << index)
|
||||
{
|
||||
XRPL_ASSERT(index >= 0 && (mask_ != 0), "xrpl::packed_spinlock::packed_spinlock : valid index and mask");
|
||||
XRPL_ASSERT(
|
||||
index >= 0 && (mask_ != 0),
|
||||
"xrpl::packed_spinlock::packed_spinlock : valid index and mask");
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
@@ -175,7 +178,10 @@ public:
|
||||
T expected = 0;
|
||||
|
||||
return lock_.compare_exchange_weak(
|
||||
expected, std::numeric_limits<T>::max(), std::memory_order_acquire, std::memory_order_relaxed);
|
||||
expected,
|
||||
std::numeric_limits<T>::max(),
|
||||
std::memory_order_acquire,
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -11,7 +11,9 @@ std::string
|
||||
strHex(FwdIt begin, FwdIt end)
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible<typename std::iterator_traits<FwdIt>::iterator_category, std::forward_iterator_tag>::value,
|
||||
std::is_convertible<
|
||||
typename std::iterator_traits<FwdIt>::iterator_category,
|
||||
std::forward_iterator_tag>::value,
|
||||
"FwdIt must be a forward iterator");
|
||||
std::string result;
|
||||
result.reserve(2 * std::distance(begin, end));
|
||||
|
||||
@@ -31,7 +31,9 @@ class tagged_integer
|
||||
tagged_integer<Int, Tag>,
|
||||
boost::bitwise<
|
||||
tagged_integer<Int, Tag>,
|
||||
boost::unit_steppable<tagged_integer<Int, Tag>, boost::shiftable<tagged_integer<Int, Tag>>>>>>
|
||||
boost::unit_steppable<
|
||||
tagged_integer<Int, Tag>,
|
||||
boost::shiftable<tagged_integer<Int, Tag>>>>>>
|
||||
{
|
||||
private:
|
||||
Int m_value;
|
||||
@@ -44,10 +46,14 @@ public:
|
||||
|
||||
template <
|
||||
class OtherInt,
|
||||
class = typename std::enable_if<std::is_integral<OtherInt>::value && sizeof(OtherInt) <= sizeof(Int)>::type>
|
||||
class = typename std::enable_if<
|
||||
std::is_integral<OtherInt>::value &&
|
||||
sizeof(OtherInt) <= sizeof(Int)>::type>
|
||||
explicit constexpr tagged_integer(OtherInt value) noexcept : m_value(value)
|
||||
{
|
||||
static_assert(sizeof(tagged_integer) == sizeof(Int), "tagged_integer is adding padding");
|
||||
static_assert(
|
||||
sizeof(tagged_integer) == sizeof(Int),
|
||||
"tagged_integer is adding padding");
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -32,7 +32,11 @@ private:
|
||||
|
||||
public:
|
||||
io_latency_probe(duration const& period, boost::asio::io_context& ios)
|
||||
: m_count(1), m_period(period), m_ios(ios), m_timer(m_ios), m_cancel(false)
|
||||
: m_count(1)
|
||||
, m_period(period)
|
||||
, m_ios(ios)
|
||||
, m_timer(m_ios)
|
||||
, m_cancel(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -87,7 +91,10 @@ public:
|
||||
std::lock_guard lock(m_mutex);
|
||||
if (m_cancel)
|
||||
throw std::logic_error("io_latency_probe is canceled");
|
||||
boost::asio::post(m_ios, sample_op<Handler>(std::forward<Handler>(handler), Clock::now(), false, this));
|
||||
boost::asio::post(
|
||||
m_ios,
|
||||
sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), false, this));
|
||||
}
|
||||
|
||||
/** Initiate continuous i/o latency sampling.
|
||||
@@ -101,7 +108,10 @@ public:
|
||||
std::lock_guard lock(m_mutex);
|
||||
if (m_cancel)
|
||||
throw std::logic_error("io_latency_probe is canceled");
|
||||
boost::asio::post(m_ios, sample_op<Handler>(std::forward<Handler>(handler), Clock::now(), true, this));
|
||||
boost::asio::post(
|
||||
m_ios,
|
||||
sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), true, this));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -141,8 +151,15 @@ private:
|
||||
bool m_repeat;
|
||||
io_latency_probe* m_probe;
|
||||
|
||||
sample_op(Handler const& handler, time_point const& start, bool repeat, io_latency_probe* probe)
|
||||
: m_handler(handler), m_start(start), m_repeat(repeat), m_probe(probe)
|
||||
sample_op(
|
||||
Handler const& handler,
|
||||
time_point const& start,
|
||||
bool repeat,
|
||||
io_latency_probe* probe)
|
||||
: m_handler(handler)
|
||||
, m_start(start)
|
||||
, m_repeat(repeat)
|
||||
, m_probe(probe)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
m_probe,
|
||||
@@ -197,19 +214,23 @@ private:
|
||||
// Calculate when we want to sample again, and
|
||||
// adjust for the expected latency.
|
||||
//
|
||||
typename Clock::time_point const when(now + m_probe->m_period - 2 * elapsed);
|
||||
typename Clock::time_point const when(
|
||||
now + m_probe->m_period - 2 * elapsed);
|
||||
|
||||
if (when <= now)
|
||||
{
|
||||
// The latency is too high to maintain the desired
|
||||
// period so don't bother with a timer.
|
||||
//
|
||||
boost::asio::post(m_probe->m_ios, sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
boost::asio::post(
|
||||
m_probe->m_ios,
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_probe->m_timer.expires_after(when - now);
|
||||
m_probe->m_timer.async_wait(sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
m_probe->m_timer.async_wait(
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,7 +241,9 @@ private:
|
||||
if (!m_probe)
|
||||
return;
|
||||
typename Clock::time_point const now(Clock::now());
|
||||
boost::asio::post(m_probe->m_ios, sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
boost::asio::post(
|
||||
m_probe->m_ios,
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -29,7 +29,8 @@ private:
|
||||
time_point now_;
|
||||
|
||||
public:
|
||||
explicit manual_clock(time_point const& now = time_point(duration(0))) : now_(now)
|
||||
explicit manual_clock(time_point const& now = time_point(duration(0)))
|
||||
: now_(now)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,7 +44,9 @@ public:
|
||||
void
|
||||
set(time_point const& when)
|
||||
{
|
||||
XRPL_ASSERT(!Clock::is_steady || when >= now_, "beast::manual_clock::set(time_point) : forward input");
|
||||
XRPL_ASSERT(
|
||||
!Clock::is_steady || when >= now_,
|
||||
"beast::manual_clock::set(time_point) : forward input");
|
||||
now_ = when;
|
||||
}
|
||||
|
||||
@@ -61,7 +64,8 @@ public:
|
||||
advance(std::chrono::duration<Rep, Period> const& elapsed)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
!Clock::is_steady || (now_ + elapsed) >= now_, "beast::manual_clock::advance(duration) : forward input");
|
||||
!Clock::is_steady || (now_ + elapsed) >= now_,
|
||||
"beast::manual_clock::advance(duration) : forward input");
|
||||
now_ += elapsed;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,14 @@ namespace beast {
|
||||
|
||||
/** Expire aged container items past the specified age. */
|
||||
template <class AgedContainer, class Rep, class Period>
|
||||
typename std::enable_if<is_aged_container<AgedContainer>::value, std::size_t>::type
|
||||
expire(AgedContainer& c, std::chrono::duration<Rep, Period> const& age)
|
||||
typename std::enable_if<is_aged_container<AgedContainer>::value, std::size_t>::
|
||||
type
|
||||
expire(AgedContainer& c, std::chrono::duration<Rep, Period> const& age)
|
||||
{
|
||||
std::size_t n(0);
|
||||
auto const expired(c.clock().now() - age);
|
||||
for (auto iter(c.chronological.cbegin()); iter != c.chronological.cend() && iter.when() <= expired;)
|
||||
for (auto iter(c.chronological.cbegin());
|
||||
iter != c.chronological.cend() && iter.when() <= expired;)
|
||||
{
|
||||
iter = c.erase(iter);
|
||||
++n;
|
||||
|
||||
@@ -15,7 +15,8 @@ template <
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key const, T>>>
|
||||
using aged_map = detail::aged_ordered_container<false, true, Key, T, Clock, Compare, Allocator>;
|
||||
using aged_map = detail::
|
||||
aged_ordered_container<false, true, Key, T, Clock, Compare, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ template <
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key const, T>>>
|
||||
using aged_multimap = detail::aged_ordered_container<true, true, Key, T, Clock, Compare, Allocator>;
|
||||
using aged_multimap = detail::
|
||||
aged_ordered_container<true, true, Key, T, Clock, Compare, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ template <
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less<Key>,
|
||||
class Allocator = std::allocator<Key>>
|
||||
using aged_multiset = detail::aged_ordered_container<true, false, Key, void, Clock, Compare, Allocator>;
|
||||
using aged_multiset = detail::
|
||||
aged_ordered_container<true, false, Key, void, Clock, Compare, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ template <
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less<Key>,
|
||||
class Allocator = std::allocator<Key>>
|
||||
using aged_set = detail::aged_ordered_container<false, false, Key, void, Clock, Compare, Allocator>;
|
||||
using aged_set = detail::
|
||||
aged_ordered_container<false, false, Key, void, Clock, Compare, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,15 @@ template <
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key const, T>>>
|
||||
using aged_unordered_map = detail::aged_unordered_container<false, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
|
||||
using aged_unordered_map = detail::aged_unordered_container<
|
||||
false,
|
||||
true,
|
||||
Key,
|
||||
T,
|
||||
Clock,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,15 @@ template <
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key const, T>>>
|
||||
using aged_unordered_multimap = detail::aged_unordered_container<true, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
|
||||
using aged_unordered_multimap = detail::aged_unordered_container<
|
||||
true,
|
||||
true,
|
||||
Key,
|
||||
T,
|
||||
Clock,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,15 @@ template <
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<Key>>
|
||||
using aged_unordered_multiset =
|
||||
detail::aged_unordered_container<true, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
|
||||
using aged_unordered_multiset = detail::aged_unordered_container<
|
||||
true,
|
||||
false,
|
||||
Key,
|
||||
void,
|
||||
Clock,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,15 @@ template <
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<Key>>
|
||||
using aged_unordered_set = detail::aged_unordered_container<false, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
|
||||
using aged_unordered_set = detail::aged_unordered_container<
|
||||
false,
|
||||
false,
|
||||
Key,
|
||||
void,
|
||||
Clock,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@ template <bool is_const, class Iterator>
|
||||
class aged_container_iterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
|
||||
using iterator_category =
|
||||
typename std::iterator_traits<Iterator>::iterator_category;
|
||||
using value_type = typename std::conditional<
|
||||
is_const,
|
||||
typename Iterator::value_type::stashed::value_type const,
|
||||
typename Iterator::value_type::stashed::value_type>::type;
|
||||
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
|
||||
using difference_type =
|
||||
typename std::iterator_traits<Iterator>::difference_type;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
using time_point = typename Iterator::value_type::stashed::time_point;
|
||||
@@ -36,22 +38,31 @@ public:
|
||||
class = typename std::enable_if<
|
||||
(other_is_const == false || is_const == true) &&
|
||||
std::is_same<Iterator, OtherIterator>::value == false>::type>
|
||||
explicit aged_container_iterator(aged_container_iterator<other_is_const, OtherIterator> const& other)
|
||||
explicit aged_container_iterator(
|
||||
aged_container_iterator<other_is_const, OtherIterator> const& other)
|
||||
: m_iter(other.m_iter)
|
||||
{
|
||||
}
|
||||
|
||||
// Disable constructing a const_iterator from a non-const_iterator.
|
||||
template <bool other_is_const, class = typename std::enable_if<other_is_const == false || is_const == true>::type>
|
||||
aged_container_iterator(aged_container_iterator<other_is_const, Iterator> const& other) : m_iter(other.m_iter)
|
||||
template <
|
||||
bool other_is_const,
|
||||
class = typename std::enable_if<
|
||||
other_is_const == false || is_const == true>::type>
|
||||
aged_container_iterator(
|
||||
aged_container_iterator<other_is_const, Iterator> const& other)
|
||||
: m_iter(other.m_iter)
|
||||
{
|
||||
}
|
||||
|
||||
// Disable assigning a const_iterator to a non-const iterator
|
||||
template <bool other_is_const, class OtherIterator>
|
||||
auto
|
||||
operator=(aged_container_iterator<other_is_const, OtherIterator> const& other) ->
|
||||
typename std::enable_if<other_is_const == false || is_const == true, aged_container_iterator&>::type
|
||||
operator=(
|
||||
aged_container_iterator<other_is_const, OtherIterator> const& other) ->
|
||||
typename std::enable_if<
|
||||
other_is_const == false || is_const == true,
|
||||
aged_container_iterator&>::type
|
||||
{
|
||||
m_iter = other.m_iter;
|
||||
return *this;
|
||||
@@ -59,14 +70,16 @@ public:
|
||||
|
||||
template <bool other_is_const, class OtherIterator>
|
||||
bool
|
||||
operator==(aged_container_iterator<other_is_const, OtherIterator> const& other) const
|
||||
operator==(aged_container_iterator<other_is_const, OtherIterator> const&
|
||||
other) const
|
||||
{
|
||||
return m_iter == other.m_iter;
|
||||
}
|
||||
|
||||
template <bool other_is_const, class OtherIterator>
|
||||
bool
|
||||
operator!=(aged_container_iterator<other_is_const, OtherIterator> const& other) const
|
||||
operator!=(aged_container_iterator<other_is_const, OtherIterator> const&
|
||||
other) const
|
||||
{
|
||||
return m_iter != other.m_iter;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -17,11 +17,16 @@ namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct is_empty_base_optimization_derived
|
||||
: std::integral_constant<bool, std::is_empty<T>::value && !boost::is_final<T>::value>
|
||||
: std::integral_constant<
|
||||
bool,
|
||||
std::is_empty<T>::value && !boost::is_final<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T, int UniqueID = 0, bool isDerived = is_empty_base_optimization_derived<T>::value>
|
||||
template <
|
||||
class T,
|
||||
int UniqueID = 0,
|
||||
bool isDerived = is_empty_base_optimization_derived<T>::value>
|
||||
class empty_base_optimization : private T
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -35,7 +35,9 @@ template <std::size_t N>
|
||||
void
|
||||
setCurrentThreadName(char const (&newThreadName)[N])
|
||||
{
|
||||
static_assert(N <= maxThreadNameLength + 1, "Thread name cannot exceed 15 characters");
|
||||
static_assert(
|
||||
N <= maxThreadNameLength + 1,
|
||||
"Thread name cannot exceed 15 characters");
|
||||
|
||||
setCurrentThreadName(std::string_view(newThreadName, N - 1));
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ struct LexicalCast<std::string, In>
|
||||
std::enable_if_t<std::is_enum_v<Enumeration>, bool>
|
||||
operator()(std::string& out, Enumeration in)
|
||||
{
|
||||
out = std::to_string(static_cast<std::underlying_type_t<Enumeration>>(in));
|
||||
out = std::to_string(
|
||||
static_cast<std::underlying_type_t<Enumeration>>(in));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -51,10 +52,14 @@ struct LexicalCast<Out, std::string_view>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
static_assert(std::is_integral_v<Out>, "beast::LexicalCast can only be used with integral types");
|
||||
static_assert(
|
||||
std::is_integral_v<Out>,
|
||||
"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>
|
||||
std::enable_if_t<
|
||||
std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>,
|
||||
bool>
|
||||
operator()(Integral& out, std::string_view in) const
|
||||
{
|
||||
auto first = in.data();
|
||||
@@ -74,9 +79,10 @@ struct LexicalCast<Out, std::string_view>
|
||||
std::string result;
|
||||
|
||||
// Convert the input to lowercase
|
||||
std::transform(in.begin(), in.end(), std::back_inserter(result), [](auto c) {
|
||||
return std::tolower(static_cast<unsigned char>(c));
|
||||
});
|
||||
std::transform(
|
||||
in.begin(), in.end(), std::back_inserter(result), [](auto c) {
|
||||
return std::tolower(static_cast<unsigned char>(c));
|
||||
});
|
||||
|
||||
if (result == "1" || result == "true")
|
||||
{
|
||||
@@ -134,7 +140,8 @@ struct LexicalCast<Out, char const*>
|
||||
bool
|
||||
operator()(Out& out, char const* in) const
|
||||
{
|
||||
XRPL_ASSERT(in, "beast::detail::LexicalCast(char const*) : non-null input");
|
||||
XRPL_ASSERT(
|
||||
in, "beast::detail::LexicalCast(char const*) : non-null input");
|
||||
return LexicalCast<Out, std::string_view>()(out, in);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -55,7 +55,8 @@ 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 =
|
||||
typename beast::detail::CopyConst<N, typename N::value_type>::type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
|
||||
@@ -14,16 +14,21 @@ class LockFreeStackIterator
|
||||
{
|
||||
protected:
|
||||
using Node = typename Container::Node;
|
||||
using NodePtr = typename std::conditional<IsConst, Node const*, Node*>::type;
|
||||
using NodePtr =
|
||||
typename std::conditional<IsConst, Node const*, Node*>::type;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = typename Container::value_type;
|
||||
using difference_type = typename Container::difference_type;
|
||||
using pointer =
|
||||
typename std::conditional<IsConst, typename Container::const_pointer, typename Container::pointer>::type;
|
||||
using reference =
|
||||
typename std::conditional<IsConst, typename Container::const_reference, typename Container::reference>::type;
|
||||
using pointer = typename std::conditional<
|
||||
IsConst,
|
||||
typename Container::const_pointer,
|
||||
typename Container::pointer>::type;
|
||||
using reference = typename std::conditional<
|
||||
IsConst,
|
||||
typename Container::const_reference,
|
||||
typename Container::reference>::type;
|
||||
|
||||
LockFreeStackIterator() : m_node()
|
||||
{
|
||||
@@ -34,7 +39,9 @@ public:
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
explicit LockFreeStackIterator(LockFreeStackIterator<Container, OtherIsConst> const& other) : m_node(other.m_node)
|
||||
explicit LockFreeStackIterator(
|
||||
LockFreeStackIterator<Container, OtherIsConst> const& other)
|
||||
: m_node(other.m_node)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -153,7 +160,8 @@ public:
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator = LockFreeStackIterator<LockFreeStack<Element, Tag>, false>;
|
||||
using const_iterator = LockFreeStackIterator<LockFreeStack<Element, Tag>, true>;
|
||||
using const_iterator =
|
||||
LockFreeStackIterator<LockFreeStack<Element, Tag>, true>;
|
||||
|
||||
LockFreeStack() : m_end(nullptr), m_head(&m_end)
|
||||
{
|
||||
@@ -191,7 +199,11 @@ public:
|
||||
{
|
||||
first = (old_head == &m_end);
|
||||
node->m_next = old_head;
|
||||
} while (!m_head.compare_exchange_strong(old_head, node, std::memory_order_release, std::memory_order_relaxed));
|
||||
} while (!m_head.compare_exchange_strong(
|
||||
old_head,
|
||||
node,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed));
|
||||
return first;
|
||||
}
|
||||
|
||||
@@ -214,7 +226,11 @@ public:
|
||||
if (node == &m_end)
|
||||
return nullptr;
|
||||
new_head = node->m_next.load();
|
||||
} while (!m_head.compare_exchange_strong(node, new_head, std::memory_order_release, std::memory_order_relaxed));
|
||||
} while (!m_head.compare_exchange_strong(
|
||||
node,
|
||||
new_head,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed));
|
||||
return static_cast<Element*>(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ template <class T>
|
||||
inline void
|
||||
reverse_bytes(T& t)
|
||||
{
|
||||
unsigned char* bytes = static_cast<unsigned char*>(std::memmove(std::addressof(t), std::addressof(t), sizeof(T)));
|
||||
unsigned char* 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]);
|
||||
}
|
||||
@@ -52,7 +53,11 @@ template <class T, class Hasher>
|
||||
inline void
|
||||
maybe_reverse_bytes(T& t, Hasher&)
|
||||
{
|
||||
maybe_reverse_bytes(t, std::integral_constant<bool, Hasher::endian != boost::endian::order::native>{});
|
||||
maybe_reverse_bytes(
|
||||
t,
|
||||
std::integral_constant<
|
||||
bool,
|
||||
Hasher::endian != boost::endian::order::native>{});
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@@ -66,8 +71,10 @@ maybe_reverse_bytes(T& t, Hasher&)
|
||||
|
||||
template <class T>
|
||||
struct is_uniquely_represented
|
||||
: public std::
|
||||
integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value || std::is_pointer<T>::value>
|
||||
: public std::integral_constant<
|
||||
bool,
|
||||
std::is_integral<T>::value || std::is_enum<T>::value ||
|
||||
std::is_pointer<T>::value>
|
||||
{
|
||||
explicit is_uniquely_represented() = default;
|
||||
};
|
||||
@@ -85,7 +92,8 @@ struct is_uniquely_represented<T volatile> : public is_uniquely_represented<T>
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_uniquely_represented<T const volatile> : public is_uniquely_represented<T>
|
||||
struct is_uniquely_represented<T const volatile>
|
||||
: public is_uniquely_represented<T>
|
||||
{
|
||||
explicit is_uniquely_represented() = default;
|
||||
};
|
||||
@@ -96,7 +104,8 @@ template <class T, class U>
|
||||
struct is_uniquely_represented<std::pair<T, U>>
|
||||
: public std::integral_constant<
|
||||
bool,
|
||||
is_uniquely_represented<T>::value && is_uniquely_represented<U>::value &&
|
||||
is_uniquely_represented<T>::value &&
|
||||
is_uniquely_represented<U>::value &&
|
||||
sizeof(T) + sizeof(U) == sizeof(std::pair<T, U>)>
|
||||
{
|
||||
explicit is_uniquely_represented() = default;
|
||||
@@ -108,7 +117,8 @@ template <class... T>
|
||||
struct is_uniquely_represented<std::tuple<T...>>
|
||||
: public std::integral_constant<
|
||||
bool,
|
||||
std::conjunction_v<is_uniquely_represented<T>...> && sizeof(std::tuple<T...>) == (sizeof(T) + ...)>
|
||||
std::conjunction_v<is_uniquely_represented<T>...> &&
|
||||
sizeof(std::tuple<T...>) == (sizeof(T) + ...)>
|
||||
{
|
||||
explicit is_uniquely_represented() = default;
|
||||
};
|
||||
@@ -125,8 +135,10 @@ struct is_uniquely_represented<T[N]> : public is_uniquely_represented<T>
|
||||
|
||||
template <class T, std::size_t N>
|
||||
struct is_uniquely_represented<std::array<T, N>>
|
||||
: public std::
|
||||
integral_constant<bool, is_uniquely_represented<T>::value && sizeof(T) * N == sizeof(std::array<T, N>)>
|
||||
: public std::integral_constant<
|
||||
bool,
|
||||
is_uniquely_represented<T>::value &&
|
||||
sizeof(T) * N == sizeof(std::array<T, N>)>
|
||||
{
|
||||
explicit is_uniquely_represented() = default;
|
||||
};
|
||||
@@ -146,10 +158,12 @@ struct is_uniquely_represented<std::array<T, N>>
|
||||
*/
|
||||
/** @{ */
|
||||
template <class T, class HashAlgorithm>
|
||||
struct is_contiguously_hashable : public std::integral_constant<
|
||||
bool,
|
||||
is_uniquely_represented<T>::value &&
|
||||
(sizeof(T) == 1 || HashAlgorithm::endian == boost::endian::order::native)>
|
||||
struct is_contiguously_hashable
|
||||
: public std::integral_constant<
|
||||
bool,
|
||||
is_uniquely_represented<T>::value &&
|
||||
(sizeof(T) == 1 ||
|
||||
HashAlgorithm::endian == boost::endian::order::native)>
|
||||
{
|
||||
explicit is_contiguously_hashable() = default;
|
||||
};
|
||||
@@ -159,7 +173,8 @@ struct is_contiguously_hashable<T[N], HashAlgorithm>
|
||||
: public std::integral_constant<
|
||||
bool,
|
||||
is_uniquely_represented<T[N]>::value &&
|
||||
(sizeof(T) == 1 || HashAlgorithm::endian == boost::endian::order::native)>
|
||||
(sizeof(T) == 1 ||
|
||||
HashAlgorithm::endian == boost::endian::order::native)>
|
||||
{
|
||||
explicit is_contiguously_hashable() = default;
|
||||
};
|
||||
@@ -204,7 +219,8 @@ hash_append(Hasher& h, T const& t) noexcept
|
||||
template <class Hasher, class T>
|
||||
inline std::enable_if_t<
|
||||
!is_contiguously_hashable<T, Hasher>::value &&
|
||||
(std::is_integral<T>::value || std::is_pointer<T>::value || std::is_enum<T>::value)>
|
||||
(std::is_integral<T>::value || std::is_pointer<T>::value ||
|
||||
std::is_enum<T>::value)>
|
||||
hash_append(Hasher& h, T t) noexcept
|
||||
{
|
||||
detail::reverse_bytes(t);
|
||||
@@ -238,11 +254,15 @@ hash_append(Hasher& h, T (&a)[N]) noexcept;
|
||||
|
||||
template <class Hasher, class CharT, class Traits, class Alloc>
|
||||
std::enable_if_t<!is_contiguously_hashable<CharT, Hasher>::value>
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
|
||||
|
||||
template <class Hasher, class CharT, class Traits, class Alloc>
|
||||
std::enable_if_t<is_contiguously_hashable<CharT, Hasher>::value>
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
|
||||
|
||||
template <class Hasher, class T, class U>
|
||||
std::enable_if_t<!is_contiguously_hashable<std::pair<T, U>, Hasher>::value>
|
||||
@@ -274,10 +294,14 @@ 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<!is_contiguously_hashable<Key, Hasher>::value>
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
|
||||
template <class Hasher, class Key, class Compare, class Alloc>
|
||||
std::enable_if_t<is_contiguously_hashable<Key, Hasher>::value>
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
|
||||
template <class Hasher, class T0, class T1, class... T>
|
||||
void
|
||||
hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept;
|
||||
@@ -296,7 +320,9 @@ hash_append(Hasher& h, T (&a)[N]) noexcept
|
||||
|
||||
template <class Hasher, class CharT, class Traits, class Alloc>
|
||||
inline std::enable_if_t<!is_contiguously_hashable<CharT, Hasher>::value>
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
std::basic_string<CharT, Traits, Alloc> const& s) noexcept
|
||||
{
|
||||
for (auto c : s)
|
||||
hash_append(h, c);
|
||||
@@ -305,7 +331,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<is_contiguously_hashable<CharT, Hasher>::value>
|
||||
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
std::basic_string<CharT, Traits, Alloc> const& s) noexcept
|
||||
{
|
||||
h(s.data(), s.size() * sizeof(CharT));
|
||||
hash_append(h, s.size());
|
||||
@@ -314,7 +342,8 @@ 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<!is_contiguously_hashable<std::pair<T, U>, Hasher>::value>
|
||||
inline std::enable_if_t<
|
||||
!is_contiguously_hashable<std::pair<T, U>, Hasher>::value>
|
||||
hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
|
||||
{
|
||||
hash_append(h, p.first, p.second);
|
||||
@@ -351,14 +380,18 @@ hash_append(Hasher& h, std::array<T, N> const& a) noexcept
|
||||
|
||||
template <class Hasher, class Key, class Compare, class Alloc>
|
||||
std::enable_if_t<!is_contiguously_hashable<Key, Hasher>::value>
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
{
|
||||
for (auto const& t : v)
|
||||
hash_append(h, t);
|
||||
}
|
||||
template <class Hasher, class Key, class Compare, class Alloc>
|
||||
std::enable_if_t<is_contiguously_hashable<Key, Hasher>::value>
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
{
|
||||
h(&(v.begin()), v.size() * sizeof(Key));
|
||||
}
|
||||
@@ -381,7 +414,10 @@ hash_one(Hasher& h, T const& t) noexcept
|
||||
|
||||
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
|
||||
tuple_hash(
|
||||
Hasher& h,
|
||||
std::tuple<T...> const& t,
|
||||
std::index_sequence<I...>) noexcept
|
||||
{
|
||||
for_each_item(hash_one(h, std::get<I>(t))...);
|
||||
}
|
||||
@@ -389,7 +425,8 @@ tuple_hash(Hasher& h, std::tuple<T...> const& t, std::index_sequence<I...>) noex
|
||||
} // namespace detail
|
||||
|
||||
template <class Hasher, class... T>
|
||||
inline std::enable_if_t<!is_contiguously_hashable<std::tuple<T...>, Hasher>::value>
|
||||
inline std::enable_if_t<
|
||||
!is_contiguously_hashable<std::tuple<T...>, Hasher>::value>
|
||||
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
|
||||
{
|
||||
detail::tuple_hash(h, t, std::index_sequence_for<T...>{});
|
||||
@@ -415,7 +452,9 @@ hash_append(Hasher& h, std::chrono::duration<Rep, Period> const& d) noexcept
|
||||
|
||||
template <class Hasher, class Clock, class Duration>
|
||||
inline void
|
||||
hash_append(Hasher& h, std::chrono::time_point<Clock, Duration> const& tp) noexcept
|
||||
hash_append(
|
||||
Hasher& h,
|
||||
std::chrono::time_point<Clock, Duration> const& tp) noexcept
|
||||
{
|
||||
hash_append(h, tp.time_since_epoch());
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ private:
|
||||
{
|
||||
std::memcpy(writeBuffer_.data(), data, len);
|
||||
writeBuffer_ = writeBuffer_.subspan(len);
|
||||
readBuffer_ = std::span{std::begin(buffer_), buffer_.size() - writeBuffer_.size()};
|
||||
readBuffer_ = std::span{
|
||||
std::begin(buffer_), buffer_.size() - writeBuffer_.size()};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +98,8 @@ private:
|
||||
{
|
||||
if (seed_.has_value())
|
||||
{
|
||||
return XXH3_64bits_withSeed(readBuffer_.data(), readBuffer_.size(), *seed_);
|
||||
return XXH3_64bits_withSeed(
|
||||
readBuffer_.data(), readBuffer_.size(), *seed_);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -126,13 +128,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <class Seed, std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
||||
template <
|
||||
class Seed,
|
||||
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
||||
explicit xxhasher(Seed seed) : seed_(seed)
|
||||
{
|
||||
resetBuffers();
|
||||
}
|
||||
|
||||
template <class Seed, std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
||||
template <
|
||||
class Seed,
|
||||
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
||||
xxhasher(Seed seed, Seed) : seed_(seed)
|
||||
{
|
||||
resetBuffers();
|
||||
|
||||
@@ -23,7 +23,9 @@ public:
|
||||
@param journal Destination for logging output.
|
||||
*/
|
||||
static std::shared_ptr<StatsDCollector>
|
||||
New(IP::Endpoint const& address, std::string const& prefix, Journal journal);
|
||||
New(IP::Endpoint const& address,
|
||||
std::string const& prefix,
|
||||
Journal journal);
|
||||
};
|
||||
|
||||
} // namespace insight
|
||||
|
||||
@@ -26,7 +26,8 @@ struct ci_equal_pred
|
||||
operator()(char c1, char c2)
|
||||
{
|
||||
// VFALCO TODO Use a table lookup here
|
||||
return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2));
|
||||
return std::tolower(static_cast<unsigned char>(c1)) ==
|
||||
std::tolower(static_cast<unsigned char>(c2));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -96,7 +97,8 @@ trim_right(String const& s)
|
||||
*/
|
||||
template <
|
||||
class FwdIt,
|
||||
class Result = std::vector<std::basic_string<typename std::iterator_traits<FwdIt>::value_type>>,
|
||||
class Result = std::vector<
|
||||
std::basic_string<typename std::iterator_traits<FwdIt>::value_type>>,
|
||||
class Char>
|
||||
Result
|
||||
split(FwdIt first, FwdIt last, Char delim)
|
||||
@@ -170,7 +172,10 @@ split(FwdIt first, FwdIt last, Char delim)
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class FwdIt, class Result = std::vector<std::basic_string<typename std::iterator_traits<FwdIt>::value_type>>>
|
||||
template <
|
||||
class FwdIt,
|
||||
class Result = std::vector<
|
||||
std::basic_string<typename std::iterator_traits<FwdIt>::value_type>>>
|
||||
Result
|
||||
split_commas(FwdIt first, FwdIt last)
|
||||
{
|
||||
@@ -218,7 +223,8 @@ public:
|
||||
bool
|
||||
operator==(list_iterator const& other) const
|
||||
{
|
||||
return other.it_ == it_ && other.end_ == end_ && other.value_.size() == value_.size();
|
||||
return other.it_ == it_ && other.end_ == end_ &&
|
||||
other.value_.size() == value_.size();
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -282,12 +288,14 @@ list_iterator::increment()
|
||||
++it_;
|
||||
if (it_ == end_)
|
||||
{
|
||||
value_ = boost::string_ref(&*start, std::distance(start, it_));
|
||||
value_ = boost::string_ref(
|
||||
&*start, std::distance(start, it_));
|
||||
return;
|
||||
}
|
||||
if (*it_ == '"')
|
||||
{
|
||||
value_ = boost::string_ref(&*start, std::distance(start, it_));
|
||||
value_ = boost::string_ref(
|
||||
&*start, std::distance(start, it_));
|
||||
++it_;
|
||||
return;
|
||||
}
|
||||
@@ -313,7 +321,8 @@ list_iterator::increment()
|
||||
++it_;
|
||||
if (it_ == end_ || *it_ == ',' || is_lws(*it_))
|
||||
{
|
||||
value_ = boost::string_ref(&*start, std::distance(start, it_));
|
||||
value_ =
|
||||
boost::string_ref(&*start, std::distance(start, it_));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -335,7 +344,8 @@ inline boost::iterator_range<list_iterator>
|
||||
make_list(boost::string_ref const& field)
|
||||
{
|
||||
return boost::iterator_range<list_iterator>{
|
||||
list_iterator{field.begin(), field.end()}, list_iterator{field.end(), field.end()}};
|
||||
list_iterator{field.begin(), field.end()},
|
||||
list_iterator{field.end(), field.end()}};
|
||||
}
|
||||
|
||||
/** Returns true if the specified token exists in the list.
|
||||
@@ -357,8 +367,12 @@ bool
|
||||
is_keep_alive(boost::beast::http::message<isRequest, Body, Fields> const& m)
|
||||
{
|
||||
if (m.version() <= 10)
|
||||
return boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists("keep-alive");
|
||||
return !boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists("close");
|
||||
return boost::beast::http::token_list{
|
||||
m[boost::beast::http::field::connection]}
|
||||
.exists("keep-alive");
|
||||
return !boost::beast::http::token_list{
|
||||
m[boost::beast::http::field::connection]}
|
||||
.exists("close");
|
||||
}
|
||||
|
||||
} // namespace rfc2616
|
||||
|
||||
@@ -31,7 +31,9 @@ protected:
|
||||
boost::asio::io_context ios_;
|
||||
|
||||
private:
|
||||
boost::optional<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>> work_;
|
||||
boost::optional<boost::asio::executor_work_guard<
|
||||
boost::asio::io_context::executor_type>>
|
||||
work_;
|
||||
std::vector<std::thread> threads_;
|
||||
std::mutex m_;
|
||||
std::condition_variable cv_;
|
||||
@@ -41,7 +43,8 @@ public:
|
||||
/// The type of yield context passed to functions.
|
||||
using yield_context = boost::asio::yield_context;
|
||||
|
||||
explicit enable_yield_to(std::size_t concurrency = 1) : work_(boost::asio::make_work_guard(ios_))
|
||||
explicit enable_yield_to(std::size_t concurrency = 1)
|
||||
: work_(boost::asio::make_work_guard(ios_))
|
||||
{
|
||||
threads_.reserve(concurrency);
|
||||
while (concurrency--)
|
||||
|
||||
@@ -23,7 +23,12 @@ global_suites()
|
||||
template <class Suite>
|
||||
struct insert_suite
|
||||
{
|
||||
insert_suite(char const* name, char const* module, char const* library, bool manual, int priority)
|
||||
insert_suite(
|
||||
char const* name,
|
||||
char const* module,
|
||||
char const* library,
|
||||
bool manual,
|
||||
int priority)
|
||||
{
|
||||
global_suites().insert<Suite>(name, module, library, manual, priority);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,8 @@ public:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
selector::selector(mode_t mode, std::string const& pattern) : mode_(mode), pat_(pattern)
|
||||
selector::selector(mode_t mode, std::string const& pattern)
|
||||
: mode_(mode), pat_(pattern)
|
||||
{
|
||||
if (mode_ == automatch && pattern.empty())
|
||||
mode_ = all;
|
||||
|
||||
@@ -140,7 +140,10 @@ reporter<_>::results::add(suite_results const& r)
|
||||
if (elapsed >= std::chrono::seconds{1})
|
||||
{
|
||||
auto const iter = std::lower_bound(
|
||||
top.begin(), top.end(), elapsed, [](run_time const& t1, typename clock_type::duration const& t2) {
|
||||
top.begin(),
|
||||
top.end(),
|
||||
elapsed,
|
||||
[](run_time const& t1, typename clock_type::duration const& t2) {
|
||||
return t1.second > t2;
|
||||
});
|
||||
if (iter != top.end())
|
||||
@@ -173,8 +176,10 @@ reporter<_>::~reporter()
|
||||
os_ << std::setw(8) << fmtdur(i.second) << " " << i.first << '\n';
|
||||
}
|
||||
auto const elapsed = clock_type::now() - results_.start;
|
||||
os_ << fmtdur(elapsed) << ", " << amount{results_.suites, "suite"} << ", " << amount{results_.cases, "case"} << ", "
|
||||
<< amount{results_.total, "test"} << " total, " << amount{results_.failed, "failure"} << std::endl;
|
||||
os_ << fmtdur(elapsed) << ", " << amount{results_.suites, "suite"} << ", "
|
||||
<< amount{results_.cases, "case"} << ", "
|
||||
<< amount{results_.total, "test"} << " total, "
|
||||
<< amount{results_.failed, "failure"} << std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
@@ -209,7 +214,9 @@ void
|
||||
reporter<_>::on_case_begin(std::string const& name)
|
||||
{
|
||||
case_results_ = case_results(name);
|
||||
os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name)) << std::endl;
|
||||
os_ << suite_results_.name
|
||||
<< (case_results_.name.empty() ? "" : (" " + case_results_.name))
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
@@ -232,7 +239,8 @@ reporter<_>::on_fail(std::string const& reason)
|
||||
{
|
||||
++case_results_.failed;
|
||||
++case_results_.total;
|
||||
os_ << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason << std::endl;
|
||||
os_ << "#" << case_results_.total << " failed"
|
||||
<< (reason.empty() ? "" : ": ") << reason << std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
|
||||
@@ -24,7 +24,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
test(bool pass_, std::string const& reason_) : pass(pass_), reason(reason_)
|
||||
test(bool pass_, std::string const& reason_)
|
||||
: pass(pass_), reason(reason_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -92,13 +92,17 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
|
||||
template <
|
||||
class CharT,
|
||||
class Traits = std::char_traits<CharT>,
|
||||
class Allocator = std::allocator<CharT>>
|
||||
class log_os : public std::basic_ostream<CharT, Traits>
|
||||
{
|
||||
log_buf<CharT, Traits, Allocator> buf_;
|
||||
|
||||
public:
|
||||
explicit log_os(suite& self) : std::basic_ostream<CharT, Traits>(&buf_), buf_(self)
|
||||
explicit log_os(suite& self)
|
||||
: std::basic_ostream<CharT, Traits>(&buf_), buf_(self)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -237,7 +241,11 @@ public:
|
||||
|
||||
template <class Condition, class String>
|
||||
bool
|
||||
expect(Condition const& shouldBeTrue, String const& reason, char const* file, int line);
|
||||
expect(
|
||||
Condition const& shouldBeTrue,
|
||||
String const& reason,
|
||||
char const* file,
|
||||
int line);
|
||||
/** @} */
|
||||
|
||||
//
|
||||
@@ -341,7 +349,8 @@ public:
|
||||
}
|
||||
|
||||
template <class T>
|
||||
scoped_testcase(suite& self, std::stringstream& ss, T const& t) : suite_(self), ss_(ss)
|
||||
scoped_testcase(suite& self, std::stringstream& ss, T const& t)
|
||||
: suite_(self), ss_(ss)
|
||||
{
|
||||
ss_.clear();
|
||||
ss_.str({});
|
||||
@@ -414,7 +423,11 @@ suite::expect(Condition const& shouldBeTrue, String const& reason)
|
||||
|
||||
template <class Condition, class String>
|
||||
bool
|
||||
suite::expect(Condition const& shouldBeTrue, String const& reason, char const* file, int line)
|
||||
suite::expect(
|
||||
Condition const& shouldBeTrue,
|
||||
String const& reason,
|
||||
char const* file,
|
||||
int line)
|
||||
{
|
||||
if (shouldBeTrue)
|
||||
{
|
||||
@@ -563,7 +576,8 @@ suite::run(runner& r)
|
||||
|
||||
If the condition is false, the file and line number are reported.
|
||||
*/
|
||||
#define BEAST_EXPECTS(cond, reason) ((cond) ? (pass(), true) : (fail((reason), __FILE__, __LINE__), false))
|
||||
#define BEAST_EXPECTS(cond, reason) \
|
||||
((cond) ? (pass(), true) : (fail((reason), __FILE__, __LINE__), false))
|
||||
#endif
|
||||
|
||||
} // namespace unit_test
|
||||
@@ -573,9 +587,11 @@ suite::run(runner& r)
|
||||
|
||||
// detail:
|
||||
// This inserts the suite with the given manual flag
|
||||
#define BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, manual, priority) \
|
||||
static beast::unit_test::detail::insert_suite<Class##_test> Library##Module##Class##_test_instance( \
|
||||
#Class, #Module, #Library, manual, priority)
|
||||
#define BEAST_DEFINE_TESTSUITE_INSERT( \
|
||||
Class, Module, Library, manual, priority) \
|
||||
static beast::unit_test::detail::insert_suite<Class##_test> \
|
||||
Library##Module##Class##_test_instance( \
|
||||
#Class, #Module, #Library, manual, priority)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -630,7 +646,8 @@ suite::run(runner& r)
|
||||
|
||||
#else
|
||||
#include <xrpl/beast/unit_test/global_suites.h>
|
||||
#define BEAST_DEFINE_TESTSUITE(Class, Module, Library) BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, false, 0)
|
||||
#define BEAST_DEFINE_TESTSUITE(Class, Module, Library) \
|
||||
BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, false, 0)
|
||||
#define BEAST_DEFINE_TESTSUITE_MANUAL(Class, Module, Library) \
|
||||
BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, true, 0)
|
||||
#define BEAST_DEFINE_TESTSUITE_PRIO(Class, Module, Library, Priority) \
|
||||
|
||||
@@ -28,7 +28,13 @@ class suite_info
|
||||
run_type run_;
|
||||
|
||||
public:
|
||||
suite_info(std::string name, std::string module, std::string library, bool manual, int priority, run_type run)
|
||||
suite_info(
|
||||
std::string name,
|
||||
std::string module,
|
||||
std::string library,
|
||||
bool manual,
|
||||
int priority,
|
||||
run_type run)
|
||||
: name_(std::move(name))
|
||||
, module_(std::move(module))
|
||||
, library_(std::move(library))
|
||||
@@ -82,8 +88,10 @@ public:
|
||||
{
|
||||
// we want higher priority suites sorted first, thus the negation
|
||||
// of priority value here
|
||||
return std::forward_as_tuple(-lhs.priority_, lhs.library_, lhs.module_, lhs.name_) <
|
||||
std::forward_as_tuple(-rhs.priority_, rhs.library_, rhs.module_, rhs.name_);
|
||||
return std::forward_as_tuple(
|
||||
-lhs.priority_, lhs.library_, lhs.module_, lhs.name_) <
|
||||
std::forward_as_tuple(
|
||||
-rhs.priority_, rhs.library_, rhs.module_, rhs.name_);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,10 +100,20 @@ public:
|
||||
/// Convenience for producing suite_info for a given test type.
|
||||
template <class Suite>
|
||||
suite_info
|
||||
make_suite_info(std::string name, std::string module, std::string library, bool manual, int priority)
|
||||
make_suite_info(
|
||||
std::string name,
|
||||
std::string module,
|
||||
std::string library,
|
||||
bool manual,
|
||||
int priority)
|
||||
{
|
||||
return suite_info(
|
||||
std::move(name), std::move(module), std::move(library), manual, priority, [](runner& r) { Suite{}(r); });
|
||||
std::move(name),
|
||||
std::move(module),
|
||||
std::move(library),
|
||||
manual,
|
||||
priority,
|
||||
[](runner& r) { Suite{}(r); });
|
||||
}
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
@@ -33,14 +33,24 @@ public:
|
||||
*/
|
||||
template <class Suite>
|
||||
void
|
||||
insert(char const* name, char const* module, char const* library, bool manual, int priority);
|
||||
insert(
|
||||
char const* name,
|
||||
char const* module,
|
||||
char const* library,
|
||||
bool manual,
|
||||
int priority);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Suite>
|
||||
void
|
||||
suite_list::insert(char const* name, char const* module, char const* library, bool manual, int priority)
|
||||
suite_list::insert(
|
||||
char const* name,
|
||||
char const* module,
|
||||
char const* library,
|
||||
bool manual,
|
||||
int priority)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
@@ -55,7 +65,8 @@ suite_list::insert(char const* name, char const* module, char const* library, bo
|
||||
BOOST_ASSERT(result.second); // Duplicate type
|
||||
}
|
||||
#endif
|
||||
cont().emplace(make_suite_info<Suite>(name, module, library, manual, priority));
|
||||
cont().emplace(
|
||||
make_suite_info<Suite>(name, module, library, manual, priority));
|
||||
}
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
@@ -45,7 +45,8 @@ 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 =
|
||||
std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
t_ = std::thread(&thread::run, this, std::move(b));
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,8 @@ public:
|
||||
class ScopedStream
|
||||
{
|
||||
public:
|
||||
ScopedStream(ScopedStream const& other) : ScopedStream(other.m_sink, other.m_level)
|
||||
ScopedStream(ScopedStream const& other)
|
||||
: ScopedStream(other.m_sink, other.m_level)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -166,12 +167,16 @@ public:
|
||||
};
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
static_assert(std::is_default_constructible<ScopedStream>::value == false, "");
|
||||
static_assert(
|
||||
std::is_default_constructible<ScopedStream>::value == false,
|
||||
"");
|
||||
static_assert(std::is_copy_constructible<ScopedStream>::value == true, "");
|
||||
static_assert(std::is_move_constructible<ScopedStream>::value == true, "");
|
||||
static_assert(std::is_copy_assignable<ScopedStream>::value == false, "");
|
||||
static_assert(std::is_move_assignable<ScopedStream>::value == false, "");
|
||||
static_assert(std::is_nothrow_destructible<ScopedStream>::value == true, "");
|
||||
static_assert(
|
||||
std::is_nothrow_destructible<ScopedStream>::value == true,
|
||||
"");
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -181,7 +186,8 @@ public:
|
||||
{
|
||||
public:
|
||||
/** Create a stream which produces no output. */
|
||||
explicit Stream() : m_sink(getNullSink()), m_level(severities::kDisabled)
|
||||
explicit Stream()
|
||||
: m_sink(getNullSink()), m_level(severities::kDisabled)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -191,7 +197,9 @@ public:
|
||||
*/
|
||||
Stream(Sink& sink, Severity level) : m_sink(sink), m_level(level)
|
||||
{
|
||||
XRPL_ASSERT(m_level < severities::kDisabled, "beast::Journal::Stream::Stream : maximum level");
|
||||
XRPL_ASSERT(
|
||||
m_level < severities::kDisabled,
|
||||
"beast::Journal::Stream::Stream : maximum level");
|
||||
}
|
||||
|
||||
/** Construct or copy another Stream. */
|
||||
@@ -422,7 +430,8 @@ class basic_logstream : public std::basic_ostream<CharT, Traits>
|
||||
detail::logstream_buf<CharT, Traits> buf_;
|
||||
|
||||
public:
|
||||
explicit basic_logstream(beast::Journal::Stream const& strm) : std::basic_ostream<CharT, Traits>(&buf_), buf_(strm)
|
||||
explicit basic_logstream(beast::Journal::Stream const& strm)
|
||||
: std::basic_ostream<CharT, Traits>(&buf_), buf_(strm)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,12 +18,16 @@ private:
|
||||
std::string prefix_;
|
||||
|
||||
public:
|
||||
explicit WrappedSink(beast::Journal::Sink& sink, std::string const& prefix = "")
|
||||
explicit WrappedSink(
|
||||
beast::Journal::Sink& sink,
|
||||
std::string const& prefix = "")
|
||||
: Sink(sink), sink_(sink), prefix_(prefix)
|
||||
{
|
||||
}
|
||||
|
||||
explicit WrappedSink(beast::Journal const& journal, std::string const& prefix = "")
|
||||
explicit WrappedSink(
|
||||
beast::Journal const& journal,
|
||||
std::string const& prefix = "")
|
||||
: WrappedSink(journal.sink(), prefix)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
#endif
|
||||
|
||||
#define XRPL_ASSERT ALWAYS_OR_UNREACHABLE
|
||||
#define XRPL_ASSERT_PARTS(cond, function, description, ...) XRPL_ASSERT(cond, function " : " description)
|
||||
#define XRPL_ASSERT_PARTS(cond, function, description, ...) \
|
||||
XRPL_ASSERT(cond, function " : " description)
|
||||
|
||||
// How to use the instrumentation macros:
|
||||
//
|
||||
|
||||
@@ -10,8 +10,10 @@ template <bool IsConst, class T>
|
||||
struct maybe_const
|
||||
{
|
||||
explicit maybe_const() = default;
|
||||
using type = typename std::
|
||||
conditional<IsConst, typename std::remove_const<T>::type const, typename std::remove_const<T>::type>::type;
|
||||
using type = typename std::conditional<
|
||||
IsConst,
|
||||
typename std::remove_const<T>::type const,
|
||||
typename std::remove_const<T>::type>::type;
|
||||
};
|
||||
|
||||
/** Alias for omitting `typename`. */
|
||||
|
||||
@@ -36,7 +36,10 @@ 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,
|
||||
class = std::enable_if_t<N % sizeof(typename Generator::result_type) == 0>>
|
||||
void
|
||||
rngfill(std::array<std::uint8_t, N>& a, Generator& g)
|
||||
{
|
||||
|
||||
@@ -76,18 +76,21 @@ private:
|
||||
std::remove_reference_t<Closure> closure_;
|
||||
|
||||
static_assert(
|
||||
std::is_same<decltype(closure_(std::declval<Args_t>()...)), Ret_t>::value,
|
||||
std::is_same<decltype(closure_(std::declval<Args_t>()...)), Ret_t>::
|
||||
value,
|
||||
"Closure arguments don't match ClosureCounter Ret_t or Args_t");
|
||||
|
||||
public:
|
||||
Substitute() = delete;
|
||||
|
||||
Substitute(Substitute const& rhs) : counter_(rhs.counter_), closure_(rhs.closure_)
|
||||
Substitute(Substitute const& rhs)
|
||||
: counter_(rhs.counter_), closure_(rhs.closure_)
|
||||
{
|
||||
++counter_;
|
||||
}
|
||||
|
||||
Substitute(Substitute&& rhs) noexcept(std::is_nothrow_move_constructible<Closure>::value)
|
||||
Substitute(Substitute&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible<Closure>::value)
|
||||
: counter_(rhs.counter_), closure_(std::move(rhs.closure_))
|
||||
{
|
||||
++counter_;
|
||||
@@ -147,11 +150,13 @@ public:
|
||||
waitForClosures_ = true;
|
||||
if (closureCount_ > 0)
|
||||
{
|
||||
if (!allClosuresDoneCond_.wait_for(lock, wait, [this] { return closureCount_ == 0; }))
|
||||
if (!allClosuresDoneCond_.wait_for(
|
||||
lock, wait, [this] { return closureCount_ == 0; }))
|
||||
{
|
||||
if (auto stream = j.error())
|
||||
stream << name << " waiting for ClosureCounter::join().";
|
||||
allClosuresDoneCond_.wait(lock, [this] { return closureCount_ == 0; });
|
||||
allClosuresDoneCond_.wait(
|
||||
lock, [this] { return closureCount_ == 0; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,20 @@
|
||||
namespace xrpl {
|
||||
|
||||
template <class F>
|
||||
JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string const& name, F&& f)
|
||||
JobQueue::Coro::Coro(
|
||||
Coro_create_t,
|
||||
JobQueue& jq,
|
||||
JobType type,
|
||||
std::string const& name,
|
||||
F&& f)
|
||||
: jq_(jq)
|
||||
, type_(type)
|
||||
, name_(name)
|
||||
, running_(false)
|
||||
, coro_(
|
||||
[this, fn = std::forward<F>(f)](boost::coroutines::asymmetric_coroutine<void>::push_type& do_yield) {
|
||||
[this, fn = std::forward<F>(f)](
|
||||
boost::coroutines::asymmetric_coroutine<void>::push_type&
|
||||
do_yield) {
|
||||
yield_ = &do_yield;
|
||||
yield();
|
||||
fn(shared_from_this());
|
||||
@@ -50,7 +57,8 @@ JobQueue::Coro::post()
|
||||
}
|
||||
|
||||
// sp keeps 'this' alive
|
||||
if (jq_.addJob(type_, name_, [this, sp = shared_from_this()]() { resume(); }))
|
||||
if (jq_.addJob(
|
||||
type_, name_, [this, sp = shared_from_this()]() { resume(); }))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -76,7 +84,8 @@ JobQueue::Coro::resume()
|
||||
auto saved = detail::getLocalValues().release();
|
||||
detail::getLocalValues().reset(&lvs_);
|
||||
std::lock_guard lock(mutex_);
|
||||
XRPL_ASSERT(static_cast<bool>(coro_), "xrpl::JobQueue::Coro::resume : is runnable");
|
||||
XRPL_ASSERT(
|
||||
static_cast<bool>(coro_), "xrpl::JobQueue::Coro::resume : is runnable");
|
||||
coro_();
|
||||
detail::getLocalValues().release();
|
||||
detail::getLocalValues().reset(saved);
|
||||
|
||||
@@ -3,16 +3,19 @@
|
||||
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/core/ClosureCounter.h>
|
||||
#include <xrpl/core/LoadMonitor.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class LoadEvent;
|
||||
class LoadMonitor;
|
||||
|
||||
// Note that this queue should only be used for CPU-bound jobs
|
||||
// It is primarily intended for signature checking
|
||||
|
||||
enum JobType {
|
||||
enum JobType : int {
|
||||
// Special type indicating an invalid job - will go away soon.
|
||||
jtINVALID = -1,
|
||||
|
||||
@@ -93,7 +96,11 @@ public:
|
||||
Job(JobType type, std::uint64_t index);
|
||||
|
||||
// VFALCO TODO try to remove the dependency on LoadMonitor.
|
||||
Job(JobType type, std::string const& name, std::uint64_t index, LoadMonitor& lm, std::function<void()> const& job);
|
||||
Job(JobType type,
|
||||
std::string const& name,
|
||||
std::uint64_t index,
|
||||
LoadMonitor& lm,
|
||||
std::function<void()> const& job);
|
||||
|
||||
JobType
|
||||
getType() const;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class LoadEvent;
|
||||
|
||||
namespace perf {
|
||||
class PerfLog;
|
||||
}
|
||||
@@ -141,11 +143,14 @@ public:
|
||||
*/
|
||||
template <
|
||||
typename JobHandler,
|
||||
typename = std::enable_if_t<std::is_same<decltype(std::declval<JobHandler&&>()()), void>::value>>
|
||||
typename = std::enable_if_t<std::is_same<
|
||||
decltype(std::declval<JobHandler&&>()()),
|
||||
void>::value>>
|
||||
bool
|
||||
addJob(JobType type, std::string const& name, JobHandler&& jobHandler)
|
||||
{
|
||||
if (auto optionalCountedJob = jobCounter_.wrap(std::forward<JobHandler>(jobHandler)))
|
||||
if (auto optionalCountedJob =
|
||||
jobCounter_.wrap(std::forward<JobHandler>(jobHandler)))
|
||||
{
|
||||
return addRefCountedJob(type, name, std::move(*optionalCountedJob));
|
||||
}
|
||||
@@ -261,7 +266,10 @@ private:
|
||||
//
|
||||
// return true if func added to queue.
|
||||
bool
|
||||
addRefCountedJob(JobType type, std::string const& name, JobFunction const& func);
|
||||
addRefCountedJob(
|
||||
JobType type,
|
||||
std::string const& name,
|
||||
JobFunction const& func);
|
||||
|
||||
// Returns the next Job we should run now.
|
||||
//
|
||||
@@ -390,7 +398,8 @@ JobQueue::postCoro(JobType t, std::string const& name, F&& f)
|
||||
Last param is the function the coroutine runs. Signature of
|
||||
void(std::shared_ptr<Coro>).
|
||||
*/
|
||||
auto coro = std::make_shared<Coro>(Coro_create_t{}, *this, t, name, std::forward<F>(f));
|
||||
auto coro = std::make_shared<Coro>(
|
||||
Coro_create_t{}, *this, t, name, std::forward<F>(f));
|
||||
if (!coro->post())
|
||||
{
|
||||
// The Coro was not successfully posted. Disable it so it's destructor
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/beast/insight/Collector.h>
|
||||
#include <xrpl/core/JobTypeInfo.h>
|
||||
#include <xrpl/core/LoadMonitor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
enum JobType : int;
|
||||
|
||||
struct JobTypeData
|
||||
{
|
||||
private:
|
||||
@@ -32,10 +35,19 @@ public:
|
||||
beast::insight::Event dequeue;
|
||||
beast::insight::Event execute;
|
||||
|
||||
JobTypeData(JobTypeInfo const& info_, beast::insight::Collector::ptr const& collector, Logs& logs) noexcept
|
||||
: m_load(logs.journal("LoadMonitor")), m_collector(collector), info(info_), waiting(0), running(0), deferred(0)
|
||||
JobTypeData(
|
||||
JobTypeInfo const& info_,
|
||||
beast::insight::Collector::ptr const& collector,
|
||||
Logs& logs) noexcept
|
||||
: m_load(logs.journal("LoadMonitor"))
|
||||
, m_collector(collector)
|
||||
, info(info_)
|
||||
, waiting(0)
|
||||
, running(0)
|
||||
, deferred(0)
|
||||
{
|
||||
m_load.setTargetLatency(info.getAverageLatency(), info.getPeakLatency());
|
||||
m_load.setTargetLatency(
|
||||
info.getAverageLatency(), info.getPeakLatency());
|
||||
|
||||
if (!info.special())
|
||||
{
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#ifndef XRPL_CORE_JOBTYPEINFO_H_INCLUDED
|
||||
#define XRPL_CORE_JOBTYPEINFO_H_INCLUDED
|
||||
|
||||
#include <xrpl/core/Job.h>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
enum JobType : int;
|
||||
|
||||
/** Holds all the 'static' information about a job, which does not change */
|
||||
class JobTypeInfo
|
||||
{
|
||||
@@ -33,7 +36,11 @@ public:
|
||||
int limit,
|
||||
std::chrono::milliseconds avgLatency,
|
||||
std::chrono::milliseconds peakLatency)
|
||||
: m_type(type), m_name(std::move(name)), m_limit(limit), m_avgLatency(avgLatency), m_peakLatency(peakLatency)
|
||||
: m_type(type)
|
||||
, m_name(std::move(name))
|
||||
, m_limit(limit)
|
||||
, m_avgLatency(avgLatency)
|
||||
, m_peakLatency(peakLatency)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,13 @@ public:
|
||||
using const_iterator = Map::const_iterator;
|
||||
|
||||
private:
|
||||
JobTypes() : m_unknown(jtINVALID, "invalid", 0, std::chrono::milliseconds{0}, std::chrono::milliseconds{0})
|
||||
JobTypes()
|
||||
: m_unknown(
|
||||
jtINVALID,
|
||||
"invalid",
|
||||
0,
|
||||
std::chrono::milliseconds{0},
|
||||
std::chrono::milliseconds{0})
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
int maxLimit = std::numeric_limits<int>::max();
|
||||
@@ -27,17 +33,22 @@ private:
|
||||
int limit,
|
||||
std::chrono::milliseconds avgLatency,
|
||||
std::chrono::milliseconds peakLatency) {
|
||||
XRPL_ASSERT(m_map.find(jt) == m_map.end(), "xrpl::JobTypes::JobTypes::add : unique job type input");
|
||||
XRPL_ASSERT(
|
||||
m_map.find(jt) == m_map.end(),
|
||||
"xrpl::JobTypes::JobTypes::add : unique job type input");
|
||||
|
||||
[[maybe_unused]] auto const inserted =
|
||||
m_map
|
||||
.emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(jt),
|
||||
std::forward_as_tuple(jt, name, limit, avgLatency, peakLatency))
|
||||
std::forward_as_tuple(
|
||||
jt, name, limit, avgLatency, peakLatency))
|
||||
.second;
|
||||
|
||||
XRPL_ASSERT(inserted == true, "xrpl::JobTypes::JobTypes::add : input is inserted");
|
||||
XRPL_ASSERT(
|
||||
inserted == true,
|
||||
"xrpl::JobTypes::JobTypes::add : input is inserted");
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
|
||||
#include <xrpl/basics/UptimeClock.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/LoadEvent.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class LoadEvent;
|
||||
|
||||
// Monitors load levels and response times
|
||||
|
||||
// VFALCO TODO Rename this. Having both LoadManager and LoadMonitor is
|
||||
@@ -27,7 +28,9 @@ public:
|
||||
addSamples(int count, std::chrono::milliseconds latency);
|
||||
|
||||
void
|
||||
setTargetLatency(std::chrono::milliseconds avg, std::chrono::milliseconds pk);
|
||||
setTargetLatency(
|
||||
std::chrono::milliseconds avg,
|
||||
std::chrono::milliseconds pk);
|
||||
|
||||
bool
|
||||
isOverTarget(std::chrono::milliseconds avg, std::chrono::milliseconds peak);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user