140 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| //---------------------------------------------------------------------------//
 | |
| // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
 | |
| //
 | |
| // Distributed under the Boost Software License, Version 1.0
 | |
| // See accompanying file LICENSE_1_0.txt or copy at
 | |
| // http://www.boost.org/LICENSE_1_0.txt
 | |
| //
 | |
| // See http://boostorg.github.com/compute for more information.
 | |
| //---------------------------------------------------------------------------//
 | |
| 
 | |
| #ifndef BOOST_COMPUTE_DETAIL_LRU_CACHE_HPP
 | |
| #define BOOST_COMPUTE_DETAIL_LRU_CACHE_HPP
 | |
| 
 | |
| #include <map>
 | |
| #include <list>
 | |
| #include <utility>
 | |
| 
 | |
| #include <boost/optional.hpp>
 | |
| 
 | |
| namespace boost {
 | |
| namespace compute {
 | |
| namespace detail {
 | |
| 
 | |
| // a cache which evicts the least recently used item when it is full
 | |
| template<class Key, class Value>
 | |
| class lru_cache
 | |
| {
 | |
| public:
 | |
|     typedef Key key_type;
 | |
|     typedef Value value_type;
 | |
|     typedef std::list<key_type> list_type;
 | |
|     typedef std::map<
 | |
|                 key_type,
 | |
|                 std::pair<value_type, typename list_type::iterator>
 | |
|             > map_type;
 | |
| 
 | |
|     lru_cache(size_t capacity)
 | |
|         : m_capacity(capacity)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     ~lru_cache()
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     size_t size() const
 | |
|     {
 | |
|         return m_map.size();
 | |
|     }
 | |
| 
 | |
|     size_t capacity() const
 | |
|     {
 | |
|         return m_capacity;
 | |
|     }
 | |
| 
 | |
|     bool empty() const
 | |
|     {
 | |
|         return m_map.empty();
 | |
|     }
 | |
| 
 | |
|     bool contains(const key_type &key)
 | |
|     {
 | |
|         return m_map.find(key) != m_map.end();
 | |
|     }
 | |
| 
 | |
|     void insert(const key_type &key, const value_type &value)
 | |
|     {
 | |
|         typename map_type::iterator i = m_map.find(key);
 | |
|         if(i == m_map.end()){
 | |
|             // insert item into the cache, but first check if it is full
 | |
|             if(size() >= m_capacity){
 | |
|                 // cache is full, evict the least recently used item
 | |
|                 evict();
 | |
|             }
 | |
| 
 | |
|             // insert the new item
 | |
|             m_list.push_front(key);
 | |
|             m_map[key] = std::make_pair(value, m_list.begin());
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     boost::optional<value_type> get(const key_type &key)
 | |
|     {
 | |
|         // lookup value in the cache
 | |
|         typename map_type::iterator i = m_map.find(key);
 | |
|         if(i == m_map.end()){
 | |
|             // value not in cache
 | |
|             return boost::none;
 | |
|         }
 | |
| 
 | |
|         // return the value, but first update its place in the most
 | |
|         // recently used list
 | |
|         typename list_type::iterator j = i->second.second;
 | |
|         if(j != m_list.begin()){
 | |
|             // move item to the front of the most recently used list
 | |
|             m_list.erase(j);
 | |
|             m_list.push_front(key);
 | |
| 
 | |
|             // update iterator in map
 | |
|             j = m_list.begin();
 | |
|             const value_type &value = i->second.first;
 | |
|             m_map[key] = std::make_pair(value, j);
 | |
| 
 | |
|             // return the value
 | |
|             return value;
 | |
|         }
 | |
|         else {
 | |
|             // the item is already at the front of the most recently
 | |
|             // used list so just return it
 | |
|             return i->second.first;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void clear()
 | |
|     {
 | |
|         m_map.clear();
 | |
|         m_list.clear();
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     void evict()
 | |
|     {
 | |
|         // evict item from the end of most recently used list
 | |
|         typename list_type::iterator i = --m_list.end();
 | |
|         m_map.erase(*i);
 | |
|         m_list.erase(i);
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     map_type m_map;
 | |
|     list_type m_list;
 | |
|     size_t m_capacity;
 | |
| };
 | |
| 
 | |
| } // end detail namespace
 | |
| } // end compute namespace
 | |
| } // end boost namespace
 | |
| 
 | |
| #endif // BOOST_COMPUTE_DETAIL_LRU_CACHE_HPP
 | 
