private overload of canonicalize

This commit is contained in:
Valentin Balaschenko
2026-07-09 17:28:50 +01:00
parent e85a421985
commit f836c4b43e
2 changed files with 48 additions and 8 deletions

View File

@@ -146,6 +146,23 @@ private:
Policy policy,
Callback&& replaceCallback = nullptr);
/** canonicalizeImpl variant for callers that already hold `mutex_`.
The unnamed `scoped_lock<mutex_type> 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 <class Policy, class Callback = std::nullptr_t>
bool
canonicalizeImpl(
std::scoped_lock<mutex_type> const&,
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
Policy policy,
Callback&& replaceCallback = nullptr);
public:
/** Replace aliased objects with originals.

View File

@@ -333,6 +333,30 @@ template <class Policy, class Callback>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeImpl(
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
Policy policy,
Callback&& replaceCallback)
{
std::scoped_lock<mutex_type> const lock(mutex_);
return canonicalizeImpl(
lock, key, data, policy, std::forward<Callback>(replaceCallback));
}
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
template <class Policy, class Callback>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeImpl(
std::scoped_lock<mutex_type> const&,
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
[[maybe_unused]] Policy policy,
@@ -352,8 +376,6 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
// passing a const argument is a compile error.
constexpr bool replaceCached = std::is_same_v<Policy, detail::ReplaceCached>;
std::scoped_lock const lock(mutex_);
auto cit = cache_.find(key);
if (cit == cache_.end())
@@ -664,15 +686,16 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
static_assert(
!IsKeyCache, "fetchAndModify is only supported for value caches, not key-only caches");
static_assert(
std::is_same_v<Mutex, std::recursive_mutex>,
"fetchAndModify requires a recursive mutex because canonicalize re-acquires mutex_ "
"internally");
std::scoped_lock const lock(mutex_);
std::scoped_lock<mutex_type> const lock(mutex_);
auto entry = std::make_shared<T>();
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");