From f836c4b43ed5802a28329590b75dde62ede3cd07 Mon Sep 17 00:00:00 2001 From: Valentin Balaschenko <13349202+vlntb@users.noreply.github.com> Date: Thu, 9 Jul 2026 17:28:50 +0100 Subject: [PATCH] private overload of canonicalize --- include/xrpl/basics/TaggedCache.h | 17 +++++++++++++ include/xrpl/basics/TaggedCache.ipp | 39 +++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/include/xrpl/basics/TaggedCache.h b/include/xrpl/basics/TaggedCache.h index 2bb49616e5..fea79c3d80 100644 --- a/include/xrpl/basics/TaggedCache.h +++ b/include/xrpl/basics/TaggedCache.h @@ -146,6 +146,23 @@ private: Policy policy, Callback&& replaceCallback = nullptr); + /** canonicalizeImpl variant for callers that already hold `mutex_`. + + The unnamed `scoped_lock const&` parameter is proof of + ownership; this overload does not acquire the lock. Use it from other + methods (e.g. fetchAndModify) that need to compose canonicalize with + additional work under a single critical section, without relying on + recursive-mutex re-entry. + */ + template + bool + canonicalizeImpl( + std::scoped_lock const&, + key_type const& key, + CanonicalizeClientPointerType data, + Policy policy, + Callback&& replaceCallback = nullptr); + public: /** Replace aliased objects with originals. diff --git a/include/xrpl/basics/TaggedCache.ipp b/include/xrpl/basics/TaggedCache.ipp index 8f50016e1b..734342fe8f 100644 --- a/include/xrpl/basics/TaggedCache.ipp +++ b/include/xrpl/basics/TaggedCache.ipp @@ -333,6 +333,30 @@ template inline bool TaggedCache:: canonicalizeImpl( + key_type const& key, + CanonicalizeClientPointerType data, + Policy policy, + Callback&& replaceCallback) +{ + std::scoped_lock const lock(mutex_); + return canonicalizeImpl( + lock, key, data, policy, std::forward(replaceCallback)); +} + +template < + class Key, + class T, + bool IsKeyCache, + class SharedWeakUnionPointer, + class SharedPointerType, + class Hash, + class KeyEqual, + class Mutex> +template +inline bool +TaggedCache:: + canonicalizeImpl( + std::scoped_lock const&, key_type const& key, CanonicalizeClientPointerType data, [[maybe_unused]] Policy policy, @@ -352,8 +376,6 @@ TaggedCache; - std::scoped_lock const lock(mutex_); - auto cit = cache_.find(key); if (cit == cache_.end()) @@ -664,15 +686,16 @@ TaggedCache, - "fetchAndModify requires a recursive mutex because canonicalize re-acquires mutex_ " - "internally"); - std::scoped_lock const lock(mutex_); + std::scoped_lock const lock(mutex_); auto entry = std::make_shared(); - canonicalize(key, entry, [](SharedPointerType const&) { return false; }); + canonicalizeImpl( + lock, + key, + entry, + detail::ReplaceDynamically{}, + [](SharedPointerType const&) { return false; }); XRPL_ASSERT( entry != nullptr, "xrpl::TaggedCache::fetchAndModify : entry present after canonicalize");