diff --git a/base/base_tests/fifo_cache_test.cpp b/base/base_tests/fifo_cache_test.cpp index f9fa25e8a6..d4e1a773df 100644 --- a/base/base_tests/fifo_cache_test.cpp +++ b/base/base_tests/fifo_cache_test.cpp @@ -6,6 +6,8 @@ #include #include +#include + using namespace std; template @@ -19,11 +21,11 @@ public: Value const & GetValue(Key const & key) { return m_cache.GetValue(key); } unordered_map const & GetMap() const { return m_cache.m_map; } - list const & GetList() const { return m_cache.m_list; } + boost::circular_buffer const & GetList() const { return m_cache.m_list; } bool IsValid() const { - set listKeys(m_cache.m_list.cbegin(), m_cache.m_list.cend()); + set listKeys(m_cache.m_list.begin(), m_cache.m_list.end()); set mapKeys; for (auto const & kv : m_cache.m_map) @@ -63,8 +65,9 @@ UNIT_TEST(FifoCache) { unordered_map expectedMap({{1 /* key */, 1 /* value */}, {2, 2}, {3, 3}}); TEST_EQUAL(cache.GetMap(), expectedMap, ()); - list expectedList({2, 3, 1}); - TEST_EQUAL(cache.GetList(), expectedList, ()); + std::list expectedList({2, 3, 1}); + boost::circular_buffer expectedCB(expectedList.cbegin(), expectedList.cend()); + TEST_EQUAL(cache.GetList(), expectedCB, ()); } TEST_EQUAL(cache.GetValue(7), 7, ()); @@ -72,8 +75,9 @@ UNIT_TEST(FifoCache) { unordered_map expectedMap({{7 /* key */, 7 /* value */}, {2, 2}, {3, 3}}); TEST_EQUAL(cache.GetMap(), expectedMap, ()); - list expectedList({7, 2, 3}); - TEST_EQUAL(cache.GetList(), expectedList, ()); + std::list expectedList({7, 2, 3}); + boost::circular_buffer expectedCB(expectedList.cbegin(), expectedList.cend()); + TEST_EQUAL(cache.GetList(), expectedCB, ()); } } diff --git a/base/fifo_cache.hpp b/base/fifo_cache.hpp index 0eeb8dc4c4..d08739fe76 100644 --- a/base/fifo_cache.hpp +++ b/base/fifo_cache.hpp @@ -4,9 +4,10 @@ #include #include -#include #include +#include + template class FifoCache { @@ -17,7 +18,10 @@ public: /// \param capacity maximum size of the cache in number of items. /// \param loader Function which is called if it's necessary to load a new item for the cache. - FifoCache(size_t capacity, Loader const & loader) : m_capacity(capacity), m_loader(loader) {} + FifoCache(size_t capacity, Loader const & loader) + : m_list(capacity), m_capacity(capacity), m_loader(loader) + { + } /// \brief Loads value, if it's necessary, by |key| with |m_loader|, puts it to cache and /// returns the reference to the value to |m_map|. @@ -28,7 +32,10 @@ public: return it->second; if (Size() >= m_capacity) - Evict(); + { + CHECK(!m_list.empty(), ()); + m_map.erase(m_list.back()); + } m_list.push_front(key); @@ -38,19 +45,10 @@ public: } private: - void Evict() - { - auto const i = --m_list.end(); - m_map.erase(*i); - m_list.erase(i); - } - size_t Size() const { return m_map.size(); } std::unordered_map m_map; - // @TODO(bykoianko) Consider using a structure like boost/circular_buffer instead of list - // but with handling overwriting shift. We need it to know to remove overwritten key from |m_map|. - std::list m_list; + boost::circular_buffer m_list; size_t m_capacity; Loader m_loader; }; diff --git a/base/internal/message.hpp b/base/internal/message.hpp index 2b549d8409..aac209d580 100644 --- a/base/internal/message.hpp +++ b/base/internal/message.hpp @@ -18,6 +18,7 @@ #include #include +#include /// @name Declarations. //@{ @@ -29,6 +30,7 @@ inline std::string DebugPrint(char t); template inline std::string DebugPrint(std::pair const & p); template inline std::string DebugPrint(std::list const & v); +template inline std::string DebugPrint(boost::circular_buffer const & v); template inline std::string DebugPrint(std::vector const & v); template > inline std::string DebugPrint(std::set const & v); template > inline std::string DebugPrint(std::multiset const & v); @@ -120,6 +122,11 @@ template inline std::string DebugPrint(std::list const & v) return ::my::impl::DebugPrintSequence(v.begin(), v.end()); } +template inline std::string DebugPrint(boost::circular_buffer const & v) +{ + return ::my::impl::DebugPrintSequence(v.begin(), v.end()); +} + template inline std::string DebugPrint(std::set const & v) { return ::my::impl::DebugPrintSequence(v.begin(), v.end());