From 2fd8331d0abc0abec6ebf0bbc1b55c4fa3734d0f Mon Sep 17 00:00:00 2001 From: JCW Date: Thu, 31 Jul 2025 13:51:35 +0100 Subject: [PATCH] Fix attempt Signed-off-by: JCW --- include/xrpl/basics/TaggedCache.h | 35 +++++++++++++++++++++++++++-- include/xrpl/basics/TaggedCache.ipp | 8 +++---- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/include/xrpl/basics/TaggedCache.h b/include/xrpl/basics/TaggedCache.h index 99c91fe393..c24338dd90 100644 --- a/include/xrpl/basics/TaggedCache.h +++ b/include/xrpl/basics/TaggedCache.h @@ -37,6 +37,28 @@ namespace ripple { +namespace detail { +template +constexpr bool IsStatelessLambdaV = std::is_empty_v && std::is_constructible_v; + +template +constexpr std::true_type IsConstexpr(Lambda); +constexpr std::false_type IsConstexpr(...); + +template +constexpr bool IsConstexprInvocableV = IsStatelessLambdaV && decltype(IsConstexpr(T{})){}; + +template > +constexpr bool ShouldTakeConstReferenceV = false; + +template +constexpr bool ShouldTakeConstReferenceV = Lambda{}(); + +template +constexpr bool ShouldTakeConstReferenceV = true; + +} + /** Map/cache combination. This class implements a cache and a map. The cache keeps objects alive in the map. The map allows multiple code paths that reference objects @@ -118,6 +140,15 @@ public: del(key_type const& key, bool valid); public: + + // We take a const reference if R (the replaceCallback) is a stateless + // lambda and can be evaluated at compile time, and it's evaluated to true, + // because there's no chance to update the parameter. + template + using SharedPointerTypeReference = std::conditional_t< + detail::ShouldTakeConstReferenceV, + SharedPointerType const&, + SharedPointerType&>; /** Replace aliased objects with originals. Due to concurrency it is possible for two separate objects with @@ -127,7 +158,7 @@ public: @param key The key corresponding to the object @param data A shared pointer to the data corresponding to the object. - @param replace Function that decides if cache should be replaced + @param replaceCallback Function that decides if cache should be replaced @return `true` If the key already existed. */ @@ -135,7 +166,7 @@ public: bool canonicalize( key_type const& key, - SharedPointerType& data, + SharedPointerTypeReference data, R&& replaceCallback); bool diff --git a/include/xrpl/basics/TaggedCache.ipp b/include/xrpl/basics/TaggedCache.ipp index 16a3f7587a..9dd1395e14 100644 --- a/include/xrpl/basics/TaggedCache.ipp +++ b/include/xrpl/basics/TaggedCache.ipp @@ -415,7 +415,7 @@ TaggedCache< Mutex>:: canonicalize( key_type const& key, - SharedPointerType& data, + SharedPointerTypeReference data, R&& replaceCallback) { // Return canonical value, store if needed, refresh in cache @@ -457,7 +457,7 @@ TaggedCache< { entry.ptr = data; } - else + else if constexpr (std::assignable_from) { data = entry.ptr.getStrong(); } @@ -473,7 +473,7 @@ TaggedCache< { entry.ptr = data; } - else + else if constexpr (std::assignable_from) { entry.ptr.convertToStrong(); data = cachedData; @@ -513,7 +513,7 @@ TaggedCache< SharedPointerType const& data) { return canonicalize( - key, const_cast(data), []() { return true; }); + key, data, []() { return true; }); } template <