Aether
SDL2 based UI Framework for NX
LRUCache.hpp
1 #ifndef AETHER_LRUCACHE_HPP
2 #define AETHER_LRUCACHE_HPP
3 
4 #include <functional>
5 #include <list>
6 #include <unordered_map>
7 
8 namespace Aether {
13  template <typename Key, typename Value>
14  class LRUCache {
15  public:
16  // Typedef some really long things
17  typedef typename std::pair<Key, Value> KeyValuePair;
18  typedef typename std::list<KeyValuePair>::iterator ListIterator;
19 
20  private:
22  std::list<KeyValuePair> items;
23 
25  std::unordered_map<Key, ListIterator> keyMap;
26 
28  std::function<void(const Key &, const Value &)> callback;
29 
31  unsigned int maxSize;
32 
33  public:
38  this->callback = nullptr;
39  this->maxSize = 100;
40  }
41 
48  LRUCache(const unsigned int size, const std::function<void(const Key &, const Value &)> & func = nullptr) {
49  this->callback = func;
50  this->maxSize = size;
51  }
52 
59  void addData(const Key & key, const Value & data) {
60  // Add data to front of cache
61  typename std::unordered_map<Key, ListIterator>::iterator it = this->keyMap.find(key);
62  this->items.push_front(KeyValuePair(key, data));
63  if (it != this->keyMap.end()) {
64  // If it was in the map, remove old value
65  this->items.erase(it->second);
66  this->keyMap.erase(it);
67  }
68  this->keyMap[key] = this->items.begin();
69 
70  // If we're oversize, remove oldest element
71  if (this->keyMap.size() > this->maxSize) {
72  // Get last element
73  typename std::list<KeyValuePair>::iterator it2 = this->items.end();
74  it2--;
75 
76  // Invoke callback if one was set
77  if (this->callback != nullptr) {
78  this->callback(it2->first, it2->second);
79  }
80 
81  // Remove from both containers
82  this->keyMap.erase(it2->first);
83  this->items.pop_back();
84  }
85  }
86 
95  Value getData(const Key & key) {
96  typename std::unordered_map<Key, ListIterator>::iterator it = this->keyMap.find(key);
97  if (it != this->keyMap.end()) {
98  // Shift data to front of list
99  this->items.splice(this->items.begin(), this->items, it->second);
100  }
101 
102  // We hope this is a valid element if key doesn't exist
103  return this->items.begin()->second;
104  }
105 
112  bool hasKey(const Key & key) {
113  return (this->keyMap.find(key) != this->keyMap.end());
114  }
115 
121  unsigned int size() {
122  return this->keyMap.size();
123  }
124 
129  if (this->callback != nullptr) {
130  for (const KeyValuePair & pair : this->items) {
131  this->callback(pair.first, pair.second);
132  }
133  }
134  }
135  };
136 };
137 
138 #endif
139 
Value getData(const Key &key)
Returns the cached value associated with the given key.
Definition: LRUCache.hpp:95
void addData(const Key &key, const Value &data)
Add data to the cache using the given key.
Definition: LRUCache.hpp:59
A basic LRU (least recently used) cache implementation. Also supports a custom callback for when an i...
Definition: LRUCache.hpp:14
~LRUCache()
Calls callback function on each stored item when deleted.
Definition: LRUCache.hpp:128
Base namespace for all Aether related classes and functions.
bool hasKey(const Key &key)
Returns if the given key has a cached value.
Definition: LRUCache.hpp:112
LRUCache(const unsigned int size, const std::function< void(const Key &, const Value &)> &func=nullptr)
Create a LRU Cache with the given size.
Definition: LRUCache.hpp:48
unsigned int size()
Returns the number of items in the cache.
Definition: LRUCache.hpp:121
LRUCache()
Default constructor initializes a cache of size 100 and no callback.
Definition: LRUCache.hpp:37