11#ifndef EIGEN_LRU_CACHE_H
12#define EIGEN_LRU_CACHE_H
17#include <unordered_map>
20#include "../InternalHeaderCheck.h"
41template <
typename Key,
typename Value,
typename Hash = std::hash<Key>,
typename KeyEqual = std::equal_to<Key>>
45 using value_type = Value;
47 explicit LruCache(std::size_t capacity) : capacity_(capacity) {
48 eigen_assert(capacity_ > 0 &&
"LruCache capacity must be positive");
51 index_.reserve(capacity_);
54 LruCache(
const LruCache&) =
delete;
55 LruCache& operator=(
const LruCache&) =
delete;
57 LruCache(LruCache&& o) noexcept : capacity_(o.capacity_), items_(std::move(o.items_)), index_(std::move(o.index_)) {}
59 LruCache& operator=(LruCache&& o)
noexcept {
61 capacity_ = o.capacity_;
62 items_ = std::move(o.items_);
63 index_ = std::move(o.index_);
68 ~LruCache() =
default;
72 Value* find(
const Key& key) {
73 auto map_it = index_.find(key);
74 if (map_it == index_.end())
return nullptr;
75 items_.splice(items_.begin(), items_, map_it->second);
76 return &map_it->second->second;
85 Value* insert(
const Key& key, Value value) {
86 if (capacity_ == 0)
return nullptr;
87 auto map_it = index_.find(key);
88 if (map_it != index_.end()) {
89 auto old_it = map_it->second;
90 items_.emplace_front(key, std::move(value));
91 map_it->second = items_.begin();
93 return &map_it->second->second;
95 if (items_.size() >= capacity_) {
96 index_.erase(items_.back().first);
99 items_.emplace_front(key, std::move(value));
100 index_.emplace(key, items_.begin());
101 return &items_.front().second;
109 std::size_t size()
const {
return items_.size(); }
110 std::size_t capacity()
const {
return capacity_; }
111 bool empty()
const {
return items_.empty(); }
114 using list_type = std::list<std::pair<Key, Value>>;
116 std::size_t capacity_;
118 std::unordered_map<Key, typename list_type::iterator, Hash, KeyEqual> index_;