diff --git a/.clang-tidy b/.clang-tidy index 26c7995631..b100938182 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -31,8 +31,10 @@ Checks: "-*, bugprone-no-escape, bugprone-non-zero-enum-to-bool-conversion, bugprone-parent-virtual-call, + bugprone-pointer-arithmetic-on-polymorphic-object, bugprone-posix-return, bugprone-redundant-branch-condition, + bugprone-reserved-identifier, bugprone-return-const-ref-from-parameter, bugprone-shared-ptr-array-mismatch, bugprone-signal-handler, @@ -49,17 +51,21 @@ Checks: "-*, bugprone-suspicious-include, bugprone-suspicious-memory-comparison, bugprone-suspicious-memset-usage, + bugprone-suspicious-missing-comma, bugprone-suspicious-realloc-usage, bugprone-suspicious-semicolon, bugprone-suspicious-string-compare, + bugprone-suspicious-stringview-data-usage, bugprone-swapped-arguments, bugprone-terminating-continue, bugprone-throw-keyword-missing, + bugprone-too-small-loop-variable, bugprone-undefined-memory-manipulation, bugprone-undelegated-constructor, bugprone-unhandled-exception-at-new, bugprone-unique-ptr-array-mismatch, bugprone-unsafe-functions, + bugprone-unused-local-non-trivial-variable, bugprone-virtual-near-miss, cppcoreguidelines-no-suspend-with-lock, cppcoreguidelines-virtual-class-destructor, @@ -85,19 +91,13 @@ Checks: "-*, performance-trivially-destructible " # --- -# more checks that have some issues that need to be resolved: +# checks that have some issues that need to be resolved: # # bugprone-crtp-constructor-accessibility, # bugprone-inc-dec-in-conditions, -# bugprone-reserved-identifier, # bugprone-move-forwarding-reference, -# bugprone-unused-local-non-trivial-variable, # bugprone-switch-missing-default-case, -# bugprone-suspicious-stringview-data-usage, -# bugprone-suspicious-missing-comma, -# bugprone-pointer-arithmetic-on-polymorphic-object, # bugprone-optional-value-conversion, -# bugprone-too-small-loop-variable, # bugprone-unused-return-value, # bugprone-use-after-move, # bugprone-unhandled-self-assignment, diff --git a/.gersemi/definitions.cmake b/.gersemi/definitions.cmake new file mode 100644 index 0000000000..13061629a4 --- /dev/null +++ b/.gersemi/definitions.cmake @@ -0,0 +1,98 @@ +# Custom CMake command definitions for gersemi formatting. +# These stubs teach gersemi the signatures of project-specific commands +# so it can format their invocations correctly. + +function(git_branch branch_val) +endfunction() + +function(isolate_headers target A B scope) +endfunction() + +function(create_symbolic_link target link) +endfunction() + +function(xrpl_add_test name) +endfunction() + +macro(exclude_from_default target_) +endmacro() + +macro(exclude_if_included target_) +endmacro() + +function(target_protobuf_sources target prefix) + set(options APPEND_PATH DESCRIPTORS) + set(oneValueArgs + LANGUAGE + OUT_VAR + EXPORT_MACRO + TARGET + PROTOC_OUT_DIR + PLUGIN + PLUGIN_OPTIONS + PROTOC_EXE + ) + set(multiValueArgs + PROTOS + IMPORT_DIRS + GENERATE_EXTENSIONS + PROTOC_OPTIONS + DEPENDENCIES + ) + cmake_parse_arguments( + THIS_FUNCTION_PREFIX + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" + ${ARGN} + ) +endfunction() + +function(add_module parent name) +endfunction() + +function(target_link_modules parent scope) +endfunction() + +function(setup_target_for_coverage_gcovr) + set(options NONE) + set(oneValueArgs BASE_DIRECTORY NAME FORMAT) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments( + THIS_FUNCTION_PREFIX + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" + ${ARGN} + ) +endfunction() + +function(add_code_coverage_to_target name scope) +endfunction() + +function(verbose_find_path variable name) + set(options + NO_CACHE + REQUIRED + OPTIONAL + NO_DEFAULT_PATH + NO_PACKAGE_ROOT_PATH + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH + NO_CMAKE_INSTALL_PREFIX + CMAKE_FIND_ROOT_PATH_BOTH + ONLY_CMAKE_FIND_ROOT_PATH + NO_CMAKE_FIND_ROOT_PATH + ) + set(oneValueArgs REGISTRY_VIEW VALIDATOR DOC) + set(multiValueArgs NAMES HINTS PATHS PATH_SUFFIXES) + cmake_parse_arguments( + THIS_FUNCTION_PREFIX + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" + ${ARGN} + ) +endfunction() diff --git a/.gersemirc b/.gersemirc new file mode 100644 index 0000000000..5abd52ffd5 --- /dev/null +++ b/.gersemirc @@ -0,0 +1 @@ +definitions: [.gersemi] diff --git a/.github/workflows/check-pr-title.yml b/.github/workflows/check-pr-title.yml new file mode 100644 index 0000000000..5c7cbd1d48 --- /dev/null +++ b/.github/workflows/check-pr-title.yml @@ -0,0 +1,10 @@ +name: Check PR title + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + branches: [develop] + +jobs: + check_title: + uses: XRPLF/actions/.github/workflows/check-pr-title.yml@943eb8277e8f4b010fde0c826ce4154c36c39509 diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index be6a92eea2..b0010fe0ba 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -46,7 +46,7 @@ jobs: # that Github considers any skipped jobs to have passed, and in # turn the required checks as well. id: changes - uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4 + uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 with: files: | # These paths are unique to `on-pr.yml`. diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 54a84a426a..0989ecd1a9 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -11,7 +11,7 @@ on: jobs: # Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks. run-hooks: - uses: XRPLF/actions/.github/workflows/pre-commit.yml@56de1bdf19639e009639a50b8d17c28ca954f267 + uses: XRPLF/actions/.github/workflows/pre-commit.yml@44856eb0d6ecb7d376370244324ab3dc8b863bad with: runs_on: ubuntu-latest container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }' diff --git a/.github/workflows/reusable-clang-tidy.yml b/.github/workflows/reusable-clang-tidy.yml index 7050d3509f..5319c1627a 100644 --- a/.github/workflows/reusable-clang-tidy.yml +++ b/.github/workflows/reusable-clang-tidy.yml @@ -31,7 +31,7 @@ jobs: - name: Get changed C++ files id: changed_files - uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4 + uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 with: files: | **/*.cpp @@ -41,7 +41,7 @@ jobs: - name: Get changed clang-tidy configuration id: changed_clang_tidy - uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4 + uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 with: files: | .clang-tidy diff --git a/cmake/XrplAddTest.cmake b/cmake/XrplAddTest.cmake index 0f8f9e2c01..2f1209e03c 100644 --- a/cmake/XrplAddTest.cmake +++ b/cmake/XrplAddTest.cmake @@ -11,7 +11,12 @@ function(xrpl_add_test name) ) add_executable(${target} ${ARGN} ${sources}) - isolate_headers(${target} "${CMAKE_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/tests/${name}" PRIVATE) + isolate_headers( + ${target} + "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/tests/${name}" + PRIVATE + ) add_test(NAME ${target} COMMAND ${target}) endfunction() diff --git a/cmake/XrplCore.cmake b/cmake/XrplCore.cmake index 1c8f5e33d6..580c4155eb 100644 --- a/cmake/XrplCore.cmake +++ b/cmake/XrplCore.cmake @@ -10,16 +10,25 @@ include(target_protobuf_sources) # so we just build them as a separate library. add_library(xrpl.libpb) set_target_properties(xrpl.libpb PROPERTIES UNITY_BUILD OFF) -target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/xrpl/proto - PROTOS include/xrpl/proto/xrpl.proto +target_protobuf_sources( + xrpl.libpb + xrpl/proto + LANGUAGE cpp + IMPORT_DIRS include/xrpl/proto + PROTOS include/xrpl/proto/xrpl.proto ) file(GLOB_RECURSE protos "include/xrpl/proto/org/*.proto") -target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/xrpl/proto - PROTOS "${protos}" +target_protobuf_sources( + xrpl.libpb + xrpl/proto + LANGUAGE cpp + IMPORT_DIRS include/xrpl/proto + PROTOS "${protos}" ) target_protobuf_sources( - xrpl.libpb xrpl/proto + xrpl.libpb + xrpl/proto LANGUAGE grpc IMPORT_DIRS include/xrpl/proto PROTOS "${protos}" diff --git a/cmake/XrplCov.cmake b/cmake/XrplCov.cmake index 109f5049fd..d81d7e689f 100644 --- a/cmake/XrplCov.cmake +++ b/cmake/XrplCov.cmake @@ -39,19 +39,15 @@ list( ) setup_target_for_coverage_gcovr( - NAME - coverage - FORMAT - ${coverage_format} + NAME coverage + FORMAT ${coverage_format} EXCLUDE - "src/test" - "src/tests" - "include/xrpl/beast/test" - "include/xrpl/beast/unit_test" - "${CMAKE_BINARY_DIR}/pb-xrpl.libpb" - DEPENDENCIES - xrpld - xrpl.tests + "src/test" + "src/tests" + "include/xrpl/beast/test" + "include/xrpl/beast/unit_test" + "${CMAKE_BINARY_DIR}/pb-xrpl.libpb" + DEPENDENCIES xrpld xrpl.tests ) add_code_coverage_to_target(opts INTERFACE) diff --git a/cmake/XrplDocs.cmake b/cmake/XrplDocs.cmake index aefffba81b..7b3e9b3b30 100644 --- a/cmake/XrplDocs.cmake +++ b/cmake/XrplDocs.cmake @@ -42,7 +42,11 @@ function(verbose_find_path variable name) endif() endfunction() -verbose_find_path(doxygen_plantuml_jar_path plantuml.jar PATH_SUFFIXES share/plantuml) +verbose_find_path( + doxygen_plantuml_jar_path + plantuml.jar + PATH_SUFFIXES share/plantuml +) verbose_find_path(doxygen_dot_path dot) # https://en.cppreference.com/w/Cppreference:Archives diff --git a/cmake/add_module.cmake b/cmake/add_module.cmake index 5b1864a0bb..316d6c627b 100644 --- a/cmake/add_module.cmake +++ b/cmake/add_module.cmake @@ -25,10 +25,16 @@ function(add_module parent name) ${target} PUBLIC "$" ) - isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}" PUBLIC + isolate_headers( + ${target} + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}" + PUBLIC ) - isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/src" - "${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}" PRIVATE + isolate_headers( + ${target} + "${CMAKE_CURRENT_SOURCE_DIR}/src" + "${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}" + PRIVATE ) endfunction() diff --git a/include/xrpl/basics/Mutex.hpp b/include/xrpl/basics/Mutex.hpp new file mode 100644 index 0000000000..18c57370b1 --- /dev/null +++ b/include/xrpl/basics/Mutex.hpp @@ -0,0 +1,155 @@ +/* + This file is part of clio: https://github.com/XRPLF/clio + Copyright (c) 2024, the clio developers. + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. +*/ + +#pragma once + +#include +#include + +namespace xrpl { + +template +class Mutex; + +/** + * @brief A lock on a mutex that provides access to the protected data. + * + * @tparam ProtectedDataType data type to hold + * @tparam LockType type of lock + * @tparam MutexType type of mutex + */ +template typename LockType, typename MutexType> +class Lock +{ + LockType lock_; + ProtectedDataType& data_; + +public: + /** @cond */ + ProtectedDataType const& + operator*() const + { + return data_; + } + + ProtectedDataType& + operator*() + { + return data_; + } + + ProtectedDataType const& + get() const + { + return data_; + } + + ProtectedDataType& + get() + { + return data_; + } + + ProtectedDataType const* + operator->() const + { + return &data_; + } + + ProtectedDataType* + operator->() + { + return &data_; + } + + operator LockType&() & + { + return lock_; + } + + operator LockType const&() const& + { + return lock_; + } + /** @endcond */ + +private: + friend class Mutex, MutexType>; + + Lock(MutexType& mutex, ProtectedDataType& data) : lock_(mutex), data_(data) + { + } +}; + +/** + * @brief A container for data that is protected by a mutex. Inspired by Mutex in Rust. + * + * @tparam ProtectedDataType data type to hold + * @tparam MutexType type of mutex + */ +template +class Mutex +{ + mutable MutexType mutex_; + ProtectedDataType data_{}; + +public: + Mutex() = default; + + /** + * @brief Construct a new Mutex object with the given data + * + * @param data The data to protect + */ + explicit Mutex(ProtectedDataType data) : data_(std::move(data)) + { + } + + /** + * @brief Make a new Mutex object with the given data + * + * @tparam Args The types of the arguments to forward to the constructor of the protected data + * @param args The arguments to forward to the constructor of the protected data + * @return The Mutex object that protects the given data + */ + template + static Mutex + make(Args&&... args) + { + return Mutex{ProtectedDataType{std::forward(args)...}}; + } + + /** + * @brief Lock the mutex and get a lock object allowing access to the protected data + * + * @tparam LockType The type of lock to use + * @return A lock on the mutex and a reference to the protected data + */ + template