Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
lru_cache.hpp
1
2#ifndef __PCL_OUTOFCORE_LRU_CACHE__
3#define __PCL_OUTOFCORE_LRU_CACHE__
4
5#include <cstddef>
6#include <cassert>
7#include <list>
8#include <map>
9#include <utility>
10
11template<typename T>
13{
14public:
15
16 virtual std::size_t
17 sizeOf () const
18 {
19 return sizeof (item);
20 }
21
22 virtual
23 ~LRUCacheItem () = default;
24
26 std::size_t timestamp;
27};
28
29template<typename KeyT, typename CacheItemT>
31{
32public:
33
34 using KeyIndex = std::list<KeyT>;
35 using KeyIndexIterator = typename KeyIndex::iterator;
36 using Cache = std::map<KeyT, std::pair<CacheItemT, typename KeyIndex::iterator> >;
37
38 LRUCache (std::size_t c) :
39 capacity_ (c)
40 {
41 assert(capacity_ != 0);
42 }
43
44 bool
45 hasKey (const KeyT& k)
46 {
47 return (cache_.find (k) != cache_.end ());
48 }
49
50 CacheItemT&
51 get (const KeyT& k)
52 {
53 // Get existing key
54 const auto it = cache_.find (k);
55 assert(it != cache_.end ());
56
57 // Move key to MRU key index
58 key_index_.splice (key_index_.end (), key_index_, (*it).second.second);
59
60 // Return the retrieved item
61 return it->second.first;
62 }
63
64 void
65 touch (const KeyT& key)
66 {
67 // Get existing key
68 const auto it = cache_.find (key);
69 assert(it != cache_.end ());
70
71 // Move key to MRU key index
72 key_index_.splice (key_index_.end (), key_index_, it->second.second);
73 }
74
75 // Record a fresh key-value pair in the cache
76 bool
77 insert (const KeyT& key, const CacheItemT& value)
78 {
79 if (cache_.find (key) != cache_.end ())
80 {
81 touch (key);
82 return true;
83 }
84
85 std::size_t size = size_;
86 std::size_t item_size = value.sizeOf ();
87 int evict_count = 0;
88
89 // Get LRU key iterator
90 auto key_it = key_index_.begin ();
91
92 while (size + item_size >= capacity_)
93 {
94 const auto cache_it = cache_.find (*key_it);
95
96 // Get tail item (Least Recently Used)
97 std::size_t tail_timestamp = cache_it->second.first.timestamp;
98 std::size_t tail_size = cache_it->second.first.sizeOf ();
99
100 // Check timestamp to see if we've completely filled the cache in one go
101 if (value.timestamp == tail_timestamp)
102 {
103 return false;
104 }
105
106 size -= tail_size;
107 ++key_it;
108 ++evict_count;
109 }
110
111 // Evict enough items to make room for the new item
112 evict (evict_count);
113
114 size_ += item_size;
115
116 // Insert most-recently-used key at the end of our key index
117 auto it = key_index_.insert (key_index_.end (), key);
118
119 // Add to cache
120 cache_.insert (std::make_pair (key, std::make_pair (value, it)));
121
122 return true;
123 }
124
125 void
126 setCapacity (std::size_t capacity)
127 {
128 capacity_ = capacity;
129 }
130
131 CacheItemT&
133 {
134 const auto it = cache_.find (key_index_.front ());
135 return it->second.first;
136 }
137
138 std::size_t
139 sizeOf (const CacheItemT& value)
140 {
141 return value.sizeOf ();
142 }
143
144 // Evict the least-recently-used item from the cache
145 bool
146 evict (int item_count=1)
147 {
148 for (int i=0; i < item_count; i++)
149 {
150 if (key_index_.empty ())
151 return false;
152
153 // Get LRU item
154 const auto it = cache_.find (key_index_.front ());
155 assert(it != cache_.end());
156
157 // Remove LRU item from cache and key index
158 size_ -= it->second.first.sizeOf ();
159 cache_.erase (it);
160 key_index_.pop_front ();
161 }
162
163 return true;
164 }
165
166 // Cache capacity in kilobytes
167 std::size_t capacity_;
168
169 // Current cache size in kilobytes
170 std::size_t size_{0};
171
172 // LRU key index LRU[0] ... MRU[N]
174
175 // LRU cache
177};
178
179#endif //__PCL_OUTOFCORE_LRU_CACHE__
bool insert(const KeyT &key, const CacheItemT &value)
Definition lru_cache.hpp:77
std::list< KeyT > KeyIndex
Definition lru_cache.hpp:34
bool hasKey(const KeyT &k)
Definition lru_cache.hpp:45
std::size_t capacity_
CacheItemT & get(const KeyT &k)
Definition lru_cache.hpp:51
void touch(const KeyT &key)
Definition lru_cache.hpp:65
void setCapacity(std::size_t capacity)
KeyIndex key_index_
std::map< KeyT, std::pair< CacheItemT, typename KeyIndex::iterator > > Cache
Definition lru_cache.hpp:36
typename KeyIndex::iterator KeyIndexIterator
Definition lru_cache.hpp:35
std::size_t size_
LRUCache(std::size_t c)
Definition lru_cache.hpp:38
std::size_t sizeOf(const CacheItemT &value)
bool evict(int item_count=1)
Cache cache_
CacheItemT & tailItem()
virtual ~LRUCacheItem()=default
std::size_t timestamp
Definition lru_cache.hpp:26
virtual std::size_t sizeOf() const
Definition lru_cache.hpp:17