/* * File: lrucache.hpp * Author: Alexander Ponomarev * * Created on June 20, 2013, 5:09 PM */ #ifndef _LRUCACHE_HPP_INCLUDED_ #define _LRUCACHE_HPP_INCLUDED_ #include #include #include #include template class lru_cache { public: typedef typename std::pair key_value_pair_t; typedef typename std::list::iterator list_iterator_t; lru_cache(size_t max_size) : _max_size(max_size) { } const key_value_pair_t &put(const key_t &key, const value_t &&value = {}) { auto it = _cache_items_map.find(key); _cache_items_list.emplace_front(key_value_pair_t(key, value)); if (it != _cache_items_map.end()) { _cache_items_list.erase(it->second); _cache_items_map.erase(it); } _cache_items_map[key] = _cache_items_list.begin(); if (_cache_items_map.size() > _max_size) { auto last = _cache_items_list.end(); last--; _cache_items_map.erase(last->first); _cache_items_list.pop_back(); } return *_cache_items_list.begin(); } const value_t &get(const key_t &key) { auto it = _cache_items_map.find(key); if (it == _cache_items_map.end()) { throw std::range_error("There is no such key in cache"); } else { _cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second); return it->second->second; } } bool exists(const key_t &key) const { return _cache_items_map.find(key) != _cache_items_map.end(); } bool touch(const key_t &key) { try { auto _ = get(key); return true; } catch (...) { put(key); return false; } } size_t size() const { return _cache_items_map.size(); } private: std::list _cache_items_list; std::unordered_map _cache_items_map; size_t _max_size; }; #endif /* _LRUCACHE_HPP_INCLUDED_ */