| 205 | // Simple cache using LRU discard policy |
| 206 | template <typename KeyType, typename ValueType> |
| 207 | class ObjectCache { |
| 208 | public: |
| 209 | typedef KeyType key_type; |
| 210 | typedef ValueType value_type; |
| 211 | |
| 212 | private: |
| 213 | typedef std::map<key_type, value_type> object_map; |
| 214 | typedef std::deque<key_type> key_rank; |
| 215 | typedef typename key_rank::iterator rank_iterator; |
| 216 | object_map _objects; |
| 217 | key_rank _ranked_keys; |
| 218 | size_t _capacity; |
| 219 | |
| 220 | inline void discard_old(size_t n = 0) { |
| 221 | if (n > _capacity) { |
| 222 | throw std::runtime_error("Insufficient capacity in cache"); |
| 223 | } |
| 224 | while (_objects.size() > _capacity - n) { |
| 225 | key_type discard_key = _ranked_keys.back(); |
| 226 | _ranked_keys.pop_back(); |
| 227 | _objects.erase(discard_key); |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | public: |
| 232 | inline ObjectCache(size_t capacity = 8) : _capacity(capacity) {} |
| 233 | inline void resize(size_t capacity) { |
| 234 | _capacity = capacity; |
| 235 | this->discard_old(); |
| 236 | } |
| 237 | inline bool contains(const key_type& k) const { |
| 238 | return (bool)_objects.count(k); |
| 239 | } |
| 240 | inline void touch(const key_type& k) { |
| 241 | if (!this->contains(k)) { |
| 242 | throw std::runtime_error("Key not found in cache"); |
| 243 | } |
| 244 | rank_iterator rank = std::find(_ranked_keys.begin(), _ranked_keys.end(), k); |
| 245 | if (rank != _ranked_keys.begin()) { |
| 246 | // Move key to front of ranks |
| 247 | _ranked_keys.erase(rank); |
| 248 | _ranked_keys.push_front(k); |
| 249 | } |
| 250 | } |
| 251 | inline value_type& get(const key_type& k) { |
| 252 | if (!this->contains(k)) { |
| 253 | throw std::runtime_error("Key not found in cache"); |
| 254 | } |
| 255 | this->touch(k); |
| 256 | return _objects[k]; |
| 257 | } |
| 258 | inline value_type& insert(const key_type& k, |
| 259 | const value_type& v = value_type()) { |
| 260 | this->discard_old(1); |
| 261 | _ranked_keys.push_front(k); |
| 262 | return _objects.insert(std::make_pair(k, v)).first->second; |
| 263 | } |
| 264 | template <typename... Args> |
nothing calls this directly
no test coverage detected