diff --git a/base/base_tests/cache_test.cpp b/base/base_tests/cache_test.cpp index 4435028ac1..2644f8ddf7 100644 --- a/base/base_tests/cache_test.cpp +++ b/base/base_tests/cache_test.cpp @@ -160,3 +160,23 @@ UNIT_TEST(CacheSmoke_6) cache.ForEachValue(SimpleMovableFunctor(&v)); TEST_EQUAL(v, vector(8, 0), ()); } + +UNIT_TEST(Cache_Init) +{ + my::Cache cache; + cache.Init(3); + + bool found = true; + cache.Find(5, found) = 'a'; + TEST(!found, ()); + + TEST_EQUAL(cache.Find(5, found), 'a', ()); + TEST(found, ()); + + cache.Init(1); + cache.Find(5, found) = 'b'; + TEST(!found, ()); + + TEST_EQUAL(cache.Find(5, found), 'b', ()); + TEST(found, ()); +} diff --git a/base/cache.hpp b/base/cache.hpp index 16f70ef139..8d81105690 100644 --- a/base/cache.hpp +++ b/base/cache.hpp @@ -1,28 +1,42 @@ #include "base/assert.hpp" #include "base/base.hpp" +#include "base/macros.hpp" + #include "std/type_traits.hpp" #include "std/utility.hpp" -#include "std/vector.hpp" + namespace my { // Simple cache that stores list of values. template class Cache { - private: - Cache(Cache const &); // Not implemented. - Cache & operator = (Cache const &); // Not implemented. + DISALLOW_COPY(Cache); public: + Cache() : m_Cache(nullptr) {} + // @logCacheSize is pow of two for number of elements in cache. explicit Cache(uint32_t logCacheSize) - : m_Cache(new Data[1 << logCacheSize]), m_HashMask((1 << logCacheSize) - 1) + { + Init(logCacheSize); + } + + Cache(Cache && r) : m_Cache(r.m_Cache), m_HashMask(r.m_HashMask) + { + r.m_Cache = nullptr; + } + + void Init(uint32_t logCacheSize) { static_assert((is_same::value || is_same::value), ""); + m_Cache = new Data[1 << logCacheSize]; + m_HashMask = (1 << logCacheSize) - 1; + // We always use cache with static constant. So debug assert is enough here. - ASSERT_GREATER ( logCacheSize, 0, () ); - ASSERT_GREATER ( m_HashMask, 0, () ); + ASSERT_GREATER(logCacheSize, 0, ()); + ASSERT_GREATER(m_HashMask, 0, ()); ASSERT_LESS(logCacheSize, 32, ()); Reset(); @@ -102,8 +116,8 @@ namespace my ValueT m_Value; }; - Data * const m_Cache; - uint32_t const m_HashMask; + Data * m_Cache; + uint32_t m_HashMask; }; // Simple cache that stores list of values and provides cache missing statistics. @@ -112,12 +126,21 @@ namespace my class CacheWithStat { public: + CacheWithStat() = default; + CacheWithStat(CacheWithStat && r) = default; + // @logCacheSize is pow of two for number of elements in cache. explicit CacheWithStat(uint32_t logCacheSize) : m_cache(logCacheSize), m_miss(0), m_access(0) { } + void Init(uint32_t logCacheSize) + { + m_cache.Init(logCacheSize); + m_miss = m_access = 0; + } + double GetCacheMiss() const { if (m_access == 0) diff --git a/routing/features_road_graph.cpp b/routing/features_road_graph.cpp index b9da490fa9..2edb0850f3 100644 --- a/routing/features_road_graph.cpp +++ b/routing/features_road_graph.cpp @@ -91,12 +91,10 @@ void FeaturesRoadGraph::CrossCountryVehicleModel::Clear() IRoadGraph::RoadInfo & FeaturesRoadGraph::RoadInfoCache::Find(FeatureID const & featureId, bool & found) { - auto itr = m_cache.find(featureId.m_mwmId); - if (itr != m_cache.end()) - return itr->second->Find(featureId.m_ind, found); - - itr = m_cache.insert(make_pair(featureId.m_mwmId, make_unique(kPowOfTwoForFeatureCacheSize))).first; - return itr->second->Find(featureId.m_ind, found); + auto res = m_cache.insert(make_pair(featureId.m_mwmId, TMwmFeatureCache())); + if (res.second) + res.first->second.Init(kPowOfTwoForFeatureCacheSize); + return res.first->second.Find(featureId.m_ind, found); } void FeaturesRoadGraph::RoadInfoCache::Clear() diff --git a/routing/features_road_graph.hpp b/routing/features_road_graph.hpp index 554db36655..a9c395d1b0 100644 --- a/routing/features_road_graph.hpp +++ b/routing/features_road_graph.hpp @@ -52,7 +52,7 @@ private: private: using TMwmFeatureCache = my::Cache; - map> m_cache; + map m_cache; }; public: