lru

#pragma once

#include <list>
#include <map>
#include <mutex>
#include <utility>
#include <shared_mutex>

// a cache which evicts the least recently used item when it is full
template <typename key_type, typename value_type>
class LruCache
{
public:
    using ListType = std::list<key_type>;
    using ListTypeIter = typename ListType::iterator; // 符号的结合性, 所以需要加上 typename
    using MapType = std::map<key_type, std::pair<value_type, ListTypeIter>>;

    LruCache() { m_capacity = 100; }

    LruCache(size_t capacity) : m_capacity(capacity) { }

    ~LruCache() { }

    size_t size() const { return m_map.size(); }

    void setCapacity(size_t c) { m_capacity = c; }

    size_t capacity() const { return m_capacity; }

    bool contains(const key_type &key)
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        return m_map.find(key) != m_map.end();
    }

    void put(const key_type &key, const value_type &value)
    {
        std::lock_guard<std::mutex> lock(m_mutex);

        typename MapType::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());
        }
    }

    bool get(const key_type &key, value_type& value)
    {
        std::lock_guard<std::mutex> lock(m_mutex);

        // lookup value in the cache
        typename MapType::iterator iter = m_map.find(key);
        if (iter == m_map.end())
        {
            // value not in cache
            return false;
        }

        // return the value, but first update its place in the most
        // recently used list
        typename ListType::iterator j = iter->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
            value = iter->second.first;
            iter->second.second = m_list.begin();
        }
        else
        {
            // the item is already at the front of the most recently
            // used list so just return it
            value = iter->second.first;
        }
        return true;
    }

    void clear()
    {
        std::lock_guard<std::mutex> lock(m_mutex);

        m_map.clear();
        m_list.clear();
    }

private:
    void evict()
    {
        // evict item from the end of most recently used list
        typename ListType::iterator i = --m_list.end();
        m_map.erase(*i);
        m_list.erase(i);
    }

private:
    MapType m_map;
    ListType m_list;
    size_t m_capacity;
    std::mutex m_mutex;
};


posted @ 2021-12-20 18:05  cnblogs_kk  阅读(77)  评论(0)    收藏  举报