#pragma once #include "StarOrderedMap.hpp" #include "StarBlockAllocator.hpp" namespace Star { template class LruCacheBase { public: typedef typename OrderedMapType::key_type Key; typedef typename OrderedMapType::mapped_type Value; typedef function 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 keys() const; List 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 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 Value& get(Key const& key, Producer producer); // Clear all cached entries. void clear(); private: OrderedMapType m_map; size_t m_maxSize; }; template , typename Allocator = BlockAllocator, 1024>> using LruCache = LruCacheBase>; template , typename Equals = std::equal_to, typename Allocator = BlockAllocator, 1024>> using HashLruCache = LruCacheBase>; template LruCacheBase::LruCacheBase(size_t maxSize) { setMaxSize(maxSize); } template size_t LruCacheBase::maxSize() const { return m_maxSize; } template void LruCacheBase::setMaxSize(size_t maxSize) { m_maxSize = max(maxSize, 1); while (m_map.size() > m_maxSize) m_map.removeFirst(); } template size_t LruCacheBase::currentSize() const { return m_map.size(); } template auto LruCacheBase::keys() const -> List { return m_map.keys(); } template auto LruCacheBase::values() const -> List { return m_map.values(); } template auto LruCacheBase::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 void LruCacheBase::set(Key const& key, Value value) { auto i = m_map.find(key); if (i == m_map.end()) { m_map.add(key, std::move(value)); } else { i->second = std::move(value); m_map.toBack(i); } } template bool LruCacheBase::remove(Key const& key) { return m_map.remove(key); } template void LruCacheBase::removeWhere(function filter) { eraseWhere(m_map, [&filter](auto& p) { return filter(p.first, p.second); }); } template template auto LruCacheBase::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 void LruCacheBase::clear() { m_map.clear(); } }