1*94c4a1e1SFrank Piva /* 2*94c4a1e1SFrank Piva * File: lrucache.hpp 3*94c4a1e1SFrank Piva * Author: Alexander Ponomarev 4*94c4a1e1SFrank Piva * 5*94c4a1e1SFrank Piva * Created on June 20, 2013, 5:09 PM 6*94c4a1e1SFrank Piva */ 7*94c4a1e1SFrank Piva 8*94c4a1e1SFrank Piva /* 9*94c4a1e1SFrank Piva * Redistribution and use in source and binary forms, with or without 10*94c4a1e1SFrank Piva modification, are permitted provided that the following conditions are met: 11*94c4a1e1SFrank Piva 12*94c4a1e1SFrank Piva * Redistributions of source code must retain the above copyright notice, this 13*94c4a1e1SFrank Piva list of conditions and the following disclaimer. 14*94c4a1e1SFrank Piva 15*94c4a1e1SFrank Piva * Redistributions in binary form must reproduce the above copyright notice, 16*94c4a1e1SFrank Piva this list of conditions and the following disclaimer in the documentation 17*94c4a1e1SFrank Piva and/or other materials provided with the distribution. 18*94c4a1e1SFrank Piva 19*94c4a1e1SFrank Piva * Neither the name of lamerman nor the names of its 20*94c4a1e1SFrank Piva contributors may be used to endorse or promote products derived from 21*94c4a1e1SFrank Piva this software without specific prior written permission. 22*94c4a1e1SFrank Piva 23*94c4a1e1SFrank Piva THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24*94c4a1e1SFrank Piva AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25*94c4a1e1SFrank Piva IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26*94c4a1e1SFrank Piva DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 27*94c4a1e1SFrank Piva FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28*94c4a1e1SFrank Piva DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29*94c4a1e1SFrank Piva SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30*94c4a1e1SFrank Piva CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31*94c4a1e1SFrank Piva OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32*94c4a1e1SFrank Piva OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33*94c4a1e1SFrank Piva */ 34*94c4a1e1SFrank Piva 35*94c4a1e1SFrank Piva #ifndef _LRUCACHE_HPP_INCLUDED_ 36*94c4a1e1SFrank Piva #define _LRUCACHE_HPP_INCLUDED_ 37*94c4a1e1SFrank Piva 38*94c4a1e1SFrank Piva #include <unordered_map> 39*94c4a1e1SFrank Piva #include <list> 40*94c4a1e1SFrank Piva #include <cstddef> 41*94c4a1e1SFrank Piva #include <stdexcept> 42*94c4a1e1SFrank Piva 43*94c4a1e1SFrank Piva namespace cache { 44*94c4a1e1SFrank Piva 45*94c4a1e1SFrank Piva template<typename key_t, typename value_t> 46*94c4a1e1SFrank Piva class lru_cache { 47*94c4a1e1SFrank Piva public: 48*94c4a1e1SFrank Piva typedef typename std::pair<key_t, value_t> key_value_pair_t; 49*94c4a1e1SFrank Piva typedef typename std::list<key_value_pair_t>::iterator list_iterator_t; 50*94c4a1e1SFrank Piva lru_cache(size_t max_size)51*94c4a1e1SFrank Piva lru_cache(size_t max_size) : 52*94c4a1e1SFrank Piva _max_size(max_size) { 53*94c4a1e1SFrank Piva } 54*94c4a1e1SFrank Piva remove_last()55*94c4a1e1SFrank Piva value_t remove_last() { 56*94c4a1e1SFrank Piva auto last = _cache_items_list.end(); 57*94c4a1e1SFrank Piva last--; 58*94c4a1e1SFrank Piva auto t = last->second; 59*94c4a1e1SFrank Piva _cache_items_map.erase(last->first); 60*94c4a1e1SFrank Piva _cache_items_list.pop_back(); 61*94c4a1e1SFrank Piva 62*94c4a1e1SFrank Piva return t; 63*94c4a1e1SFrank Piva } 64*94c4a1e1SFrank Piva put(const key_t & key,const value_t & value)65*94c4a1e1SFrank Piva value_t put(const key_t& key, const value_t& value) { 66*94c4a1e1SFrank Piva auto it = _cache_items_map.find(key); 67*94c4a1e1SFrank Piva _cache_items_list.push_front(key_value_pair_t(key, value)); 68*94c4a1e1SFrank Piva if (it != _cache_items_map.end()) { 69*94c4a1e1SFrank Piva _cache_items_list.erase(it->second); 70*94c4a1e1SFrank Piva _cache_items_map.erase(it); 71*94c4a1e1SFrank Piva } 72*94c4a1e1SFrank Piva _cache_items_map[key] = _cache_items_list.begin(); 73*94c4a1e1SFrank Piva 74*94c4a1e1SFrank Piva if (_cache_items_map.size() > _max_size) { 75*94c4a1e1SFrank Piva auto t = remove_last(); 76*94c4a1e1SFrank Piva return t; 77*94c4a1e1SFrank Piva } else { 78*94c4a1e1SFrank Piva //throw std::range_error("no cache dropped from put"); 79*94c4a1e1SFrank Piva return nullptr; 80*94c4a1e1SFrank Piva } 81*94c4a1e1SFrank Piva } 82*94c4a1e1SFrank Piva 83*94c4a1e1SFrank Piva //just retrieve value without updating position in the lru list __get(const key_t & key)84*94c4a1e1SFrank Piva value_t __get(const key_t& key) { 85*94c4a1e1SFrank Piva auto it = _cache_items_map.find(key); 86*94c4a1e1SFrank Piva if (it == _cache_items_map.end()) 87*94c4a1e1SFrank Piva return nullptr; 88*94c4a1e1SFrank Piva else 89*94c4a1e1SFrank Piva return it->second->second; 90*94c4a1e1SFrank Piva } 91*94c4a1e1SFrank Piva get(const key_t & key)92*94c4a1e1SFrank Piva value_t get(const key_t& key) { 93*94c4a1e1SFrank Piva auto it = _cache_items_map.find(key); 94*94c4a1e1SFrank Piva if (it == _cache_items_map.end()) { 95*94c4a1e1SFrank Piva //throw std::range_error("There is no such key in cache"); 96*94c4a1e1SFrank Piva return nullptr; 97*94c4a1e1SFrank Piva } else { 98*94c4a1e1SFrank Piva _cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second); 99*94c4a1e1SFrank Piva return it->second->second; 100*94c4a1e1SFrank Piva } 101*94c4a1e1SFrank Piva } 102*94c4a1e1SFrank Piva exists(const key_t & key) const103*94c4a1e1SFrank Piva bool exists(const key_t& key) const { 104*94c4a1e1SFrank Piva return _cache_items_map.find(key) != _cache_items_map.end(); 105*94c4a1e1SFrank Piva } 106*94c4a1e1SFrank Piva size() const107*94c4a1e1SFrank Piva size_t size() const { 108*94c4a1e1SFrank Piva return _cache_items_map.size(); 109*94c4a1e1SFrank Piva } 110*94c4a1e1SFrank Piva get_lru_list_ro() const111*94c4a1e1SFrank Piva const std::list<key_value_pair_t>& get_lru_list_ro() const { 112*94c4a1e1SFrank Piva return _cache_items_list; 113*94c4a1e1SFrank Piva } 114*94c4a1e1SFrank Piva 115*94c4a1e1SFrank Piva private: 116*94c4a1e1SFrank Piva std::list<key_value_pair_t> _cache_items_list; 117*94c4a1e1SFrank Piva std::unordered_map<key_t, list_iterator_t> _cache_items_map; 118*94c4a1e1SFrank Piva size_t _max_size; 119*94c4a1e1SFrank Piva }; 120*94c4a1e1SFrank Piva 121*94c4a1e1SFrank Piva } // namespace cache 122*94c4a1e1SFrank Piva 123*94c4a1e1SFrank Piva #endif /* _LRUCACHE_HPP_INCLUDED_ */ 124*94c4a1e1SFrank Piva 125