Doxygen
Loading...
Searching...
No Matches
cache.h
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#ifndef CACHE_H
17#define CACHE_H
18
19#include <list>
20#include <unordered_map>
21#include <mutex>
22#include <utility>
23#include <ctype.h>
24
25/*! Fixed size cache for value type V using keys of type K.
26 *
27 * When the maximum capacity has reached, the least recently used value is removed from the cache
28 * (LRU strategy).
29 */
30template<typename K,typename V>
31class Cache
32{
33 public:
34 using kv_pair = std::pair<K,V>;
35 using iterator = typename std::list<kv_pair>::iterator;
36 using const_iterator = typename std::list<kv_pair>::const_iterator;
37
38 //! creates a cache that can hold \a capacity elements
40 {
41 }
42
43 //! Inserts \a value under \a key in the cache
44 [[maybe_unused]] V *insert(const K &key,V &&value)
45 {
46 // reuse item if it already exists
47 auto it = m_cacheItemMap.find(key);
48 if (it != m_cacheItemMap.end())
49 {
50 // move the item to the front of the list
51 m_cacheItemList.splice(m_cacheItemList.begin(),
53 it->second);
54 std::exchange(it->second->second,value);
55 return &it->second->second;
56 }
57 // create new item
58 m_cacheItemList.push_front(kv_pair(key,std::move(value)));
59 V *result = &m_cacheItemList.front().second;
60 m_cacheItemMap[key] = m_cacheItemList.begin();
61 // remove least recently used item if cache is full
62 resize();
63 return result;
64 }
65
66 //! Inserts \a value under \a key in the cache
67 [[maybe_unused]] V *insert(const K &key,const V &value)
68 {
69 // reuse item if it already exists
70 auto it = m_cacheItemMap.find(key);
71 if (it != m_cacheItemMap.end())
72 {
73 // move the item to the front of the list
74 m_cacheItemList.splice(m_cacheItemList.begin(),
76 it->second);
77 it->second->second = value;
78 return &it->second->second;
79 }
80 // store new item
81 m_cacheItemList.push_front(kv_pair(key,value));
82 V *result = &m_cacheItemList.front().second;
83 m_cacheItemMap[key] = m_cacheItemList.begin();
84 // remove least recently used item if cache is full
85 resize();
86 return result;
87 }
88
89 //! Removes entry \a key from the cache.
90 //! \note this invalidates any iterators
91 void remove(const K &key)
92 {
93 // remove item if it already exists
94 auto it = m_cacheItemMap.find(key);
95 if (it != m_cacheItemMap.end())
96 {
97 m_cacheItemList.erase(it->second);
98 m_cacheItemMap.erase(it);
99 }
100 }
101
102 //! Finds a value in the cache given the corresponding \a key.
103 //! @returns a pointer to the value or nullptr if the key is not found in the cache
104 //! @note The hit and miss counters are updated, see hits() and misses().
105 V *find(const K &key)
106 {
107 auto it = m_cacheItemMap.find(key);
108 if (it != m_cacheItemMap.end())
109 {
110 // move the item to the front of the list
111 m_cacheItemList.splice(m_cacheItemList.begin(),
113 it->second);
114 m_hits++;
115 // return the value
116 return &it->second->second;
117 }
118 else
119 {
120 m_misses++;
121 }
122 return nullptr;
123 }
124
125 //! Returns the number of values stored in the cache.
126 size_t size() const
127 {
128 return m_cacheItemMap.size();
129 }
130
131 //! Returns the maximum number of values that can be stored in the cache.
132 size_t capacity() const
133 {
134 return m_capacity;
135 }
136
137 //! Returns how many of the find() calls did find a value in the cache.
138 uint64_t hits() const
139 {
140 return m_hits;
141 }
142
143 //! Returns how many of the find() calls did not found a value in the cache.
144 uint64_t misses() const
145 {
146 return m_misses;
147 }
148
149 //! Clears all values in the cache.
150 void clear()
151 {
152 m_cacheItemMap.clear();
153 m_cacheItemList.clear();
154 }
155
156 iterator begin() { return m_cacheItemList.begin(); }
157 iterator end() { return m_cacheItemList.end(); }
158 const_iterator begin() const { return m_cacheItemList.cbegin(); }
159 const_iterator end() const { return m_cacheItemList.cend(); }
160
161 private:
162 // remove least recently used item if cache is full
163 void resize()
164 {
165 if (m_cacheItemMap.size() > m_capacity)
166 {
167 auto last_it = m_cacheItemList.end();
168 --last_it;
169 m_cacheItemMap.erase(last_it->first);
170 m_cacheItemList.pop_back();
171 }
172 }
173
175 // list of items in the cache, sorted by most to least recently used.
176 std::list<kv_pair> m_cacheItemList;
177 // mapping for each key to a place in the list where item is found
178 std::unordered_map<K,iterator> m_cacheItemMap;
179 uint64_t m_hits=0;
180 uint64_t m_misses=0;
181};
182
183#endif
std::pair< K, V > kv_pair
Definition cache.h:34
uint64_t m_misses
Definition cache.h:180
V * insert(const K &key, V &&value)
Inserts value under key in the cache.
Definition cache.h:44
std::list< kv_pair > m_cacheItemList
Definition cache.h:176
V * insert(const K &key, const V &value)
Inserts value under key in the cache.
Definition cache.h:67
typename std::list< kv_pair >::const_iterator const_iterator
Definition cache.h:36
V * find(const K &key)
Finds a value in the cache given the corresponding key.
Definition cache.h:105
iterator end()
Definition cache.h:157
void resize()
Definition cache.h:163
const_iterator begin() const
Definition cache.h:158
size_t capacity() const
Returns the maximum number of values that can be stored in the cache.
Definition cache.h:132
iterator begin()
Definition cache.h:156
size_t m_capacity
Definition cache.h:174
typename std::list< kv_pair >::iterator iterator
Definition cache.h:35
uint64_t m_hits
Definition cache.h:179
size_t size() const
Returns the number of values stored in the cache.
Definition cache.h:126
const_iterator end() const
Definition cache.h:159
void clear()
Clears all values in the cache.
Definition cache.h:150
Cache(size_t capacity)
creates a cache that can hold capacity elements
Definition cache.h:39
uint64_t misses() const
Returns how many of the find() calls did not found a value in the cache.
Definition cache.h:144
void remove(const K &key)
Removes entry key from the cache.
Definition cache.h:91
std::unordered_map< K, iterator > m_cacheItemMap
Definition cache.h:178
uint64_t hits() const
Returns how many of the find() calls did find a value in the cache.
Definition cache.h:138