OpenTTD Source  13.2.1
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 <list>
15 #include <functional>
16 #include <unordered_map>
17 #include <stdexcept>
18 
24 template <class Tkey, class Tdata>
25 class LRUCache {
26 private:
27  typedef std::pair<Tkey, Tdata *> Tpair;
28  typedef typename std::list<Tpair>::iterator Titer;
29 
30  std::list<Tpair> data;
31  std::unordered_map<Tkey, Titer> lookup;
32 
33  const size_t capacity;
34 
35 public:
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 
58  Tdata *Insert(const Tkey key, Tdata *item)
59  {
60  Tdata *old = nullptr;
61 
62  if (this->Contains(key)) {
63  /* Replace old value. */
64  old = this->lookup[key]->second;
65  this->lookup[key]->second = item;
66  } else {
67  /* Delete least used item if maximum items cached. */
68  if (this->data.size() >= this->capacity) {
69  Tpair last = data.back();
70  this->lookup.erase(last.first);
71  this->data.pop_back();
72 
73  old = last.second;
74  }
75 
76  /* Insert new item. */
77  this->data.push_front(std::make_pair(key, item));
78  this->lookup.emplace(key, this->data.begin());
79  }
80 
81  return old;
82  }
83 
88  inline Tdata *Pop()
89  {
90  if (this->data.empty()) return nullptr;
91 
92  Tdata *value = this->data.back().second;
93  this->lookup.erase(this->data.back().first);
94  this->data.pop_back();
95  return value;
96  }
97 
104  inline Tdata *Get(const Tkey key)
105  {
106  if (this->lookup.find(key) == this->lookup.end()) throw std::out_of_range("item not found");
107  /* Move to front if needed. */
108  this->data.splice(this->data.begin(), this->data, this->lookup[key]);
109 
110  return this->data.front().second;
111  }
112 };
113 
114 #endif /* LRUCACHE_HPP */
LRUCache::Get
Tdata * Get(const Tkey key)
Get an item from the cache.
Definition: lrucache.hpp:104
LRUCache::Pop
Tdata * Pop()
Pop the least recently used item.
Definition: lrucache.hpp:88
LRUCache
Size limited cache with a least recently used eviction strategy.
Definition: lrucache.hpp:25
LRUCache::LRUCache
LRUCache(size_t max_items)
Construct new LRU cache map.
Definition: lrucache.hpp:40
LRUCache::Contains
bool Contains(const Tkey key)
Test if a key is already contained in the cache.
Definition: lrucache.hpp:47
LRUCache::capacity
const size_t capacity
Number of items to cache.
Definition: lrucache.hpp:33
LRUCache::Insert
Tdata * Insert(const Tkey key, Tdata *item)
Insert a new data item with a specified key.
Definition: lrucache.hpp:58
LRUCache::data
std::list< Tpair > data
Ordered list of all items.
Definition: lrucache.hpp:30
LRUCache::lookup
std::unordered_map< Tkey, Titer > lookup
Map of keys to items.
Definition: lrucache.hpp:31