OpenTTD Source 20250524-master-gc366e6a48e
lrucache.hpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#ifndef LRUCACHE_HPP
11#define LRUCACHE_HPP
12
13#include <utility>
14#include <unordered_map>
15
22template <class Tkey, class Tdata, class Thash = std::hash<Tkey>, class Tequality = std::equal_to<>>
23class LRUCache {
24private:
25 using PairType = std::pair<Tkey, Tdata>;
26 using StorageType = std::list<PairType>;
27 using IteratorType = StorageType::iterator;
28 using LookupType = std::unordered_map<Tkey, IteratorType, Thash, Tequality>;
29
30 StorageType data;
31 LookupType lookup;
32
33 const size_t capacity;
34
35public:
40 LRUCache(size_t max_items) : capacity(max_items) {}
41
47 inline bool Contains(const Tkey &key)
48 {
49 return this->lookup.find(key) != this->lookup.end();
50 }
51
57 void Insert(const Tkey &key, Tdata &&item)
58 {
59 auto it = this->lookup.find(key);
60 if (it != this->lookup.end()) {
61 /* Replace old value. */
62 it->second->second = std::move(item);
63 return;
64 }
65
66 /* Delete least used item if maximum items cached. */
67 if (this->data.size() >= this->capacity) {
68 this->lookup.erase(data.back().first);
69 this->data.pop_back();
70 }
71
72 /* Insert new item. */
73 this->data.emplace_front(key, std::move(item));
74 this->lookup.emplace(key, this->data.begin());
75 }
76
80 void Clear()
81 {
82 this->lookup.clear();
83 this->data.clear();
84 }
85
92 inline const Tdata &Get(const Tkey &key)
93 {
94 auto it = this->lookup.find(key);
95 if (it == this->lookup.end()) throw std::out_of_range("item not found");
96 /* Move to front if needed. */
97 this->data.splice(this->data.begin(), this->data, it->second);
98
99 return this->data.front().second;
100 }
101
108 inline Tdata *GetIfValid(const auto &key)
109 {
110 auto it = this->lookup.find(key);
111 if (it == this->lookup.end()) return nullptr;
112
113 /* Move to front if needed. */
114 this->data.splice(this->data.begin(), this->data, it->second);
115
116 return &this->data.front().second;
117 }
118};
119
120#endif /* LRUCACHE_HPP */
Size limited cache with a least recently used eviction strategy.
Definition lrucache.hpp:23
const size_t capacity
Number of items to cache.
Definition lrucache.hpp:33
StorageType data
Ordered list of all items.
Definition lrucache.hpp:30
Tdata * GetIfValid(const auto &key)
Get an item from the cache.
Definition lrucache.hpp:108
LRUCache(size_t max_items)
Construct new LRU cache map.
Definition lrucache.hpp:40
void Insert(const Tkey &key, Tdata &&item)
Insert a new data item with a specified key.
Definition lrucache.hpp:57
void Clear()
Clear the cache.
Definition lrucache.hpp:80
LookupType lookup
Map of keys to items.
Definition lrucache.hpp:31
const Tdata & Get(const Tkey &key)
Get an item from the cache.
Definition lrucache.hpp:92
bool Contains(const Tkey &key)
Test if a key is already contained in the cache.
Definition lrucache.hpp:47