Doxygen
Toggle main menu visibility
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
*/
30
template
<
typename
K,
typename
V>
31
class
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
39
Cache
(
size_t
capacity
) :
m_capacity
(
capacity
)
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(),
52
m_cacheItemList
,
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(),
75
m_cacheItemList
,
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(),
112
m_cacheItemList
,
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
174
size_t
m_capacity
;
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
Cache::kv_pair
std::pair< K, V > kv_pair
Definition
cache.h:34
Cache::m_misses
uint64_t m_misses
Definition
cache.h:180
Cache::insert
V * insert(const K &key, V &&value)
Inserts value under key in the cache.
Definition
cache.h:44
Cache::m_cacheItemList
std::list< kv_pair > m_cacheItemList
Definition
cache.h:176
Cache::insert
V * insert(const K &key, const V &value)
Inserts value under key in the cache.
Definition
cache.h:67
Cache::const_iterator
typename std::list< kv_pair >::const_iterator const_iterator
Definition
cache.h:36
Cache::find
V * find(const K &key)
Definition
cache.h:105
Cache::end
iterator end()
Definition
cache.h:157
Cache::resize
void resize()
Definition
cache.h:163
Cache::begin
const_iterator begin() const
Definition
cache.h:158
Cache::capacity
size_t capacity() const
Returns the maximum number of values that can be stored in the cache.
Definition
cache.h:132
Cache::begin
iterator begin()
Definition
cache.h:156
Cache::m_capacity
size_t m_capacity
Definition
cache.h:174
Cache::iterator
typename std::list< kv_pair >::iterator iterator
Definition
cache.h:35
Cache::m_hits
uint64_t m_hits
Definition
cache.h:179
Cache::size
size_t size() const
Returns the number of values stored in the cache.
Definition
cache.h:126
Cache::end
const_iterator end() const
Definition
cache.h:159
Cache::clear
void clear()
Clears all values in the cache.
Definition
cache.h:150
Cache::Cache
Cache(size_t capacity)
creates a cache that can hold capacity elements
Definition
cache.h:39
Cache::misses
uint64_t misses() const
Returns how many of the find() calls did not found a value in the cache.
Definition
cache.h:144
Cache::remove
void remove(const K &key)
Definition
cache.h:91
Cache::m_cacheItemMap
std::unordered_map< K, iterator > m_cacheItemMap
Definition
cache.h:178
Cache::hits
uint64_t hits() const
Returns how many of the find() calls did find a value in the cache.
Definition
cache.h:138
src
cache.h
Generated by
1.17.0