Files
rippled/include/xrpl/basics/LocalValue.h
2026-02-03 18:27:00 +00:00

125 lines
2.3 KiB
C++

#ifndef XRPL_BASICS_LOCALVALUE_H_INCLUDED
#define XRPL_BASICS_LOCALVALUE_H_INCLUDED
#include <memory>
#include <unordered_map>
namespace xrpl {
namespace detail {
struct LocalValues
{
explicit LocalValues() = default;
bool onCoro = true;
struct BasicValue
{
virtual ~BasicValue() = default;
virtual void*
get() = 0;
};
template <class T>
struct Value : BasicValue
{
T t_;
Value() = default;
explicit Value(T const& t) : t_(t)
{
}
void*
get() override
{
return &t_;
}
};
// Keys are the address of a LocalValue.
std::unordered_map<void const*, std::unique_ptr<BasicValue>> values;
};
inline LocalValues*&
getLocalValuesPtr()
{
thread_local LocalValues* ptr = nullptr;
return ptr;
}
inline LocalValues*
getOrCreateLocalValues()
{
auto& ptr = getLocalValuesPtr();
if (!ptr)
{
ptr = new LocalValues();
ptr->onCoro = false;
}
return ptr;
}
// For coroutine support, we need explicit swap functions
inline LocalValues*
releaseLocalValues()
{
auto& ptr = getLocalValuesPtr();
auto* result = ptr;
ptr = nullptr;
return result;
}
inline void
resetLocalValues(LocalValues* lvs)
{
auto& ptr = getLocalValuesPtr();
// Clean up old value if it's not a coroutine's LocalValues
if (ptr && !ptr->onCoro)
delete ptr;
ptr = lvs;
}
} // namespace detail
template <class T>
class LocalValue
{
public:
template <class... Args>
LocalValue(Args&&... args) : t_(std::forward<Args>(args)...)
{
}
/** Stores instance of T specific to the calling coroutine or thread. */
T&
operator*();
/** Stores instance of T specific to the calling coroutine or thread. */
T*
operator->()
{
return &**this;
}
private:
T t_;
};
template <class T>
T&
LocalValue<T>::operator*()
{
auto lvs = detail::getOrCreateLocalValues();
auto const iter = lvs->values.find(this);
if (iter != lvs->values.end())
return *reinterpret_cast<T*>(iter->second->get());
return *reinterpret_cast<T*>(
lvs->values.emplace(this, std::make_unique<detail::LocalValues::Value<T>>(t_)).first->second->get());
}
} // namespace xrpl
#endif