Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorVladimir Byko-Ianko <v.bykoianko@corp.mail.ru>2018-03-30 18:07:17 +0300
committerTatiana Yan <tatiana.kondakova@gmail.com>2018-04-05 12:12:34 +0300
commitfe036cbb137d187b12c3d00213facab0f4bc4078 (patch)
tree1fa9a564a1d1ea63350dd06e0a981e57f732f5a5 /base
parent62bffec3f9d4616419a107fe910dcc2f8534f7a0 (diff)
Fifo cache implementation.
Diffstat (limited to 'base')
-rw-r--r--base/CMakeLists.txt1
-rw-r--r--base/fifo_cache.hpp56
2 files changed, 57 insertions, 0 deletions
diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt
index 291d6d3189..ba5d50f8d0 100644
--- a/base/CMakeLists.txt
+++ b/base/CMakeLists.txt
@@ -23,6 +23,7 @@ set(
dfa_helpers.hpp
exception.cpp
exception.hpp
+ fifo_cache.hpp
get_time.hpp
gmtime.cpp
gmtime.hpp
diff --git a/base/fifo_cache.hpp b/base/fifo_cache.hpp
new file mode 100644
index 0000000000..da4665d57f
--- /dev/null
+++ b/base/fifo_cache.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "base/assert.hpp"
+
+#include <cstddef>
+#include <functional>
+#include <list>
+#include <unordered_map>
+
+template<class Key, class Value>
+class FifoCache
+{
+ template <typename K, typename V> friend class FifoCacheTest;
+
+public:
+ using Loader = std::function<void(Key const & key, Value & value)>;
+
+ /// \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) {}
+
+ /// \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|.
+ Value const & GetValue(const Key & key)
+ {
+ auto const it = m_map.find(key);
+ if (it != m_map.cend())
+ return it->second;
+
+ if (Size() >= m_capacity)
+ Evict();
+
+ m_list.push_front(key);
+
+ auto & v = m_map[key];
+ m_loader(key, v);
+ return (m_map[key] = v);
+ }
+
+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<Key, Value> 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<Key> m_list;
+ size_t m_capacity;
+ Loader m_loader;
+};