#ifndef XRPL_BASICS_LOCALVALUE_H_INCLUDED #define XRPL_BASICS_LOCALVALUE_H_INCLUDED #include #include #include namespace ripple { namespace detail { struct LocalValues { explicit LocalValues() = default; bool onCoro = true; struct BasicValue { virtual ~BasicValue() = default; virtual void* get() = 0; }; template 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> values; static inline void cleanup(LocalValues* lvs) { if (lvs && !lvs->onCoro) delete lvs; } }; template boost::thread_specific_ptr& getLocalValues() { static boost::thread_specific_ptr tsp( &detail::LocalValues::cleanup); return tsp; } } // namespace detail template class LocalValue { public: template LocalValue(Args&&... args) : t_(std::forward(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 T& LocalValue::operator*() { auto lvs = detail::getLocalValues().get(); if (!lvs) { lvs = new detail::LocalValues(); lvs->onCoro = false; detail::getLocalValues().reset(lvs); } else { auto const iter = lvs->values.find(this); if (iter != lvs->values.end()) return *reinterpret_cast(iter->second->get()); } return *reinterpret_cast( lvs->values .emplace(this, std::make_unique>(t_)) .first->second->get()); } } // namespace ripple #endif