diff --git a/cmake/deps/Boost.cmake b/cmake/deps/Boost.cmake index 9506693a8d..3f6eaa64e3 100644 --- a/cmake/deps/Boost.cmake +++ b/cmake/deps/Boost.cmake @@ -51,3 +51,4 @@ endif () # target_compile_options(opts INTERFACE # ignore boost headers for sanitizing # -fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt) # endif () +target_compile_options(opts INTERFACE -flarge-source-files) diff --git a/include/xrpl/basics/LocalValue.h b/include/xrpl/basics/LocalValue.h index 69256d683b..94af41a41d 100644 --- a/include/xrpl/basics/LocalValue.h +++ b/include/xrpl/basics/LocalValue.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -39,59 +41,21 @@ struct LocalValues // Keys are the address of a LocalValue. std::unordered_map> values; -}; -// Wrapper to ensure proper cleanup when thread exits -struct LocalValuesHolder -{ - LocalValues* ptr = nullptr; - - ~LocalValuesHolder() + static inline void + cleanup(LocalValues* lvs) { - if (ptr && !ptr->onCoro) - delete ptr; + if (lvs && !lvs->onCoro) + delete lvs; } }; -LocalValuesHolder& -getLocalValuesHolder(); - -inline LocalValues*& -getLocalValuesPtr() +template +boost::thread_specific_ptr& +getLocalValues() { - return getLocalValuesHolder().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; + static boost::thread_specific_ptr tsp(&detail::LocalValues::cleanup); + return tsp; } } // namespace detail @@ -124,10 +88,19 @@ template T& LocalValue::operator*() { - auto lvs = detail::getOrCreateLocalValues(); - auto const iter = lvs->values.find(this); - if (iter != lvs->values.end()) - return *reinterpret_cast(iter->second->get()); + 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()); diff --git a/include/xrpl/core/Coro.ipp b/include/xrpl/core/Coro.ipp index 8829880829..b397fcd65c 100644 --- a/include/xrpl/core/Coro.ipp +++ b/include/xrpl/core/Coro.ipp @@ -68,15 +68,13 @@ JobQueue::Coro::resume() std::lock_guard lock(jq_.m_mutex); --jq_.nSuspend_; } - auto saved = detail::releaseLocalValues(); - detail::resetLocalValues(&lvs_); + auto saved = detail::getLocalValues().release(); + detail::getLocalValues().reset(&lvs_); std::lock_guard lock(mutex_); XRPL_ASSERT(static_cast(coro_), "xrpl::JobQueue::Coro::resume : is runnable"); coro_(); - - // Restore the thread's original LocalValues - detail::releaseLocalValues(); - detail::resetLocalValues(saved); + detail::getLocalValues().release(); + detail::getLocalValues().reset(saved); std::lock_guard lk(mutex_run_); running_ = false; diff --git a/src/libxrpl/basics/LocalValue.cpp b/src/libxrpl/basics/LocalValue.cpp index 47f2d8c258..4e277f81f8 100644 --- a/src/libxrpl/basics/LocalValue.cpp +++ b/src/libxrpl/basics/LocalValue.cpp @@ -3,12 +3,5 @@ namespace xrpl { namespace detail { -LocalValuesHolder& -getLocalValuesHolder() -{ - thread_local LocalValuesHolder holder; - return holder; -} - } // namespace detail } // namespace xrpl