Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarLruCache.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/StarLruCache.hpp')
-rw-r--r--source/core/StarLruCache.hpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/source/core/StarLruCache.hpp b/source/core/StarLruCache.hpp
new file mode 100644
index 0000000..d047a37
--- /dev/null
+++ b/source/core/StarLruCache.hpp
@@ -0,0 +1,149 @@
+#ifndef STAR_LRU_CACHE_HPP
+#define STAR_LRU_CACHE_HPP
+
+#include "StarOrderedMap.hpp"
+#include "StarBlockAllocator.hpp"
+
+namespace Star {
+
+template <typename OrderedMapType>
+class LruCacheBase {
+public:
+ typedef typename OrderedMapType::key_type Key;
+ typedef typename OrderedMapType::mapped_type Value;
+
+ typedef function<Value(Key const&)> ProducerFunction;
+
+ LruCacheBase(size_t maxSize = 256);
+
+ // Max size cannot be zero, it will be clamped to at least 1 in order to hold
+ // the most recent element returned by get.
+ size_t maxSize() const;
+ void setMaxSize(size_t maxSize);
+
+ size_t currentSize() const;
+
+ List<Key> keys() const;
+ List<Value> values() const;
+
+ // If the value is in the cache, returns a pointer to it and marks it as
+ // accessed, otherwise returns nullptr.
+ Value* ptr(Key const& key);
+
+ // Put the given value into the cache.
+ void set(Key const& key, Value value);
+ // Removes the given value from the cache. If found and removed, returns
+ // true.
+ bool remove(Key const& key);
+
+ // Remove all key / value pairs matching a filter.
+ void removeWhere(function<bool(Key const&, Value&)> filter);
+
+ // If the value for the key is not found in the cache, produce it with the
+ // given producer. Producer shold take the key as an argument and return the
+ // value.
+ template <typename Producer>
+ Value& get(Key const& key, Producer producer);
+
+ // Clear all cached entries.
+ void clear();
+
+private:
+ OrderedMapType m_map;
+ size_t m_maxSize;
+};
+
+template <typename Key, typename Value, typename Compare = std::less<Key>, typename Allocator = BlockAllocator<pair<Key const, Value>, 1024>>
+using LruCache = LruCacheBase<OrderedMap<Key, Value, Compare, Allocator>>;
+
+template <typename Key, typename Value, typename Hash = Star::hash<Key>, typename Equals = std::equal_to<Key>, typename Allocator = BlockAllocator<pair<Key const, Value>, 1024>>
+using HashLruCache = LruCacheBase<OrderedHashMap<Key, Value, Hash, Equals, Allocator>>;
+
+template <typename OrderedMapType>
+LruCacheBase<OrderedMapType>::LruCacheBase(size_t maxSize) {
+ setMaxSize(maxSize);
+}
+
+template <typename OrderedMapType>
+size_t LruCacheBase<OrderedMapType>::maxSize() const {
+ return m_maxSize;
+}
+
+template <typename OrderedMapType>
+void LruCacheBase<OrderedMapType>::setMaxSize(size_t maxSize) {
+ m_maxSize = max<size_t>(maxSize, 1);
+
+ while (m_map.size() > m_maxSize)
+ m_map.removeFirst();
+}
+
+template <typename OrderedMapType>
+size_t LruCacheBase<OrderedMapType>::currentSize() const {
+ return m_map.size();
+}
+
+template <typename OrderedMapType>
+auto LruCacheBase<OrderedMapType>::keys() const -> List<Key> {
+ return m_map.keys();
+}
+
+template <typename OrderedMapType>
+auto LruCacheBase<OrderedMapType>::values() const -> List<Value> {
+ return m_map.values();
+}
+
+template <typename OrderedMapType>
+auto LruCacheBase<OrderedMapType>::ptr(Key const& key) -> Value * {
+ auto i = m_map.find(key);
+ if (i == m_map.end())
+ return nullptr;
+ i = m_map.toBack(i);
+ return &i->second;
+}
+
+template <typename OrderedMapType>
+void LruCacheBase<OrderedMapType>::set(Key const& key, Value value) {
+ auto i = m_map.find(key);
+ if (i == m_map.end()) {
+ m_map.add(key, move(value));
+ } else {
+ i->second = move(value);
+ m_map.toBack(i);
+ }
+}
+
+template <typename OrderedMapType>
+bool LruCacheBase<OrderedMapType>::remove(Key const& key) {
+ return m_map.remove(key);
+}
+
+template <typename OrderedMapType>
+void LruCacheBase<OrderedMapType>::removeWhere(function<bool(Key const&, Value&)> filter) {
+ eraseWhere(m_map, [&filter](auto& p) {
+ return filter(p.first, p.second);
+ });
+}
+
+template <typename OrderedMapType>
+template <typename Producer>
+auto LruCacheBase<OrderedMapType>::get(Key const& key, Producer producer) -> Value & {
+ while (m_map.size() > m_maxSize - 1)
+ m_map.removeFirst();
+
+ auto i = m_map.find(key);
+ if (i == m_map.end())
+ i = m_map.insert({key, producer(key)}).first;
+ else
+ i = m_map.toBack(i);
+
+ return i->second;
+}
+
+template <typename OrderedMapType>
+void LruCacheBase<OrderedMapType>::clear() {
+ m_map.clear();
+}
+
+}
+
+#endif