From e347489cfb14eb681392e63715dbe8beba4928f5 Mon Sep 17 00:00:00 2001 From: mrbald Date: Fri, 13 Dec 2024 16:39:38 +0100 Subject: [PATCH] entity cache no-grow mode --- rtb/datacache/entity_cache.hpp | 75 +++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/rtb/datacache/entity_cache.hpp b/rtb/datacache/entity_cache.hpp index f6277f3..f6229db 100644 --- a/rtb/datacache/entity_cache.hpp +++ b/rtb/datacache/entity_cache.hpp @@ -38,10 +38,31 @@ #include "rtb/core/core.hpp" #include "rtb/common/concepts.hpp" -namespace { - namespace bip = boost::interprocess ; +#include +#include +#include +#include + +// Define an error_info tag for stacktrace + +typedef boost::error_info traced; + +/** To print stack trace use *boost::get_error_info(e) after catching e */ + +template +[[noreturn]] void throw_with_stacktrace(E const& e) { + throw boost::enable_error_info(e) + << traced(boost::stacktrace::stacktrace()); } - + +#define VAV_REQUIRE(cond) \ + do { \ + if (!(cond)) [[unlikely]] \ + throw_with_stacktrace(std::runtime_error("VAV_REQUIRE assertion failed: " #cond)); \ + } while (false) + +namespace bip = boost::interprocess; + namespace datacache { template @@ -100,15 +121,16 @@ template class Container, typename .. class entity_cache { public: - using bad_alloc_exception_t = boost::interprocess::bad_alloc ; - using segment_manager_t = typename Memory::segment_manager_t ; - using segment_t = typename Memory::segment_t ; - using segment_ptr_t = boost::scoped_ptr ; - using char_allocator = boost::interprocess::allocator ; - using char_string = boost::interprocess::basic_string, char_allocator> ; - using Container_t = Container ; + using bad_alloc_exception_t = boost::interprocess::bad_alloc; + using segment_manager_t = typename Memory::segment_manager_t; + using segment_t = typename Memory::segment_t; + using segment_ptr_t = boost::scoped_ptr; + using char_allocator = boost::interprocess::allocator; + using char_string = boost::interprocess::basic_string, char_allocator>; + using Container_t = Container; using Data_t = typename Container_t::value_type; + /** Can set memory_grow_increment=0 to prevent cache from growing */ explicit entity_cache(std::string name, size_t const memory_size = ENTITY_CACHE_DEFAULT_MEMORY_SIZE, size_t const memory_grow_increment = ENTITY_CACHE_DEFAULT_MEMORY_GROW_INCREMENT) : _segment_ptr(), _container_ptr(), _store_name(), _cache_name(std::move(name)), @@ -267,22 +289,26 @@ class entity_cache LOG(debug) << boost::core::demangle(typeid(*this).name()) << " " << op_name << " failed , MEMORY AVAILABLE=" << _segment_ptr->get_free_memory(); #endif - if (grow_memory(_memory_grow_increment)) [[likely]] { - return op(); + if (_memory_grow_increment && !grow_memory(_memory_grow_increment)) [[unlikely]] { + throw; } - throw; + + return op(); } } void attach() const { - if constexpr ( !std::is_same_v ) { - _segment_ptr.reset(new segment_t(bip::open_only,_store_name.c_str()) ) ; - } - _container_ptr = _segment_ptr->template find_or_construct(_cache_name.c_str()) - (typename Container_t::ctor_args_list(), typename Container_t::allocator_type(_segment_ptr->get_segment_manager())); + if constexpr (!std::is_same_v) { + _segment_ptr.reset(new segment_t(bip::open_only, _store_name.c_str())); + } + _container_ptr = _segment_ptr->template find_or_construct(_cache_name.c_str())( + typename Container_t::ctor_args_list(), + typename Container_t::allocator_type(_segment_ptr->get_segment_manager())); } bool grow_memory(size_t size) const { + VAV_REQUIRE(_memory_grow_increment > 0); + bool success = false; try { if constexpr (!std::is_same_v) { @@ -300,7 +326,10 @@ class entity_cache template auto insert_data(Key && key, Serializable &&data) { - Memory::attach([this](){attach();}); + if (_memory_grow_increment > 0) { + Memory::attach([this]{ attach(); }); + } + Data_t item(_segment_ptr->get_segment_manager()); item.store(std::forward(key), std::forward(data)); return _container_ptr->insert(item); @@ -325,11 +354,11 @@ class entity_cache } mutable boost::scoped_ptr _segment_ptr; - mutable Container_t *_container_ptr ; - std::string _store_name ; - std::string _cache_name ; + mutable Container_t* _container_ptr{nullptr}; + std::string _store_name; + std::string _cache_name; mutable boost::interprocess::named_upgradable_mutex _named_mutex; - size_t _memory_grow_increment; + size_t _memory_grow_increment{0}; }; }