菜鸟笔记
提升您的技术认知

面试题

实现一个lru cache 算法lru cache c 三种解法java实现lru算法及编码实现lru策略缓存lru算法常见缓存算法和lru的c 实现设计循环双端队列(deque)lru 缓存结构 (c 哈希双链表实现)lru缓存机制删除单链表中的指定节点linux 内核经典面试题拼多多社招面经:redis是重点,讲一讲redis的内存模型线程、进程、协程的区别c 经典面试题面试官:我们只想要这样的c 工程师linux c/c 学习路线链表操作汇总c 11的智能指针面试题浏览器中输入url后发生的事情常用的限流算法http协议和https协议面试题网络编程面试题目总结c 后台面试题目如何实现lru算法?如何寻找无序数组中的第k大元素?布隆过滤器 - 如何在100个亿url中快速判断某url是否存在?如何实现大整数相加?c 面试题及基本知识点总结c 给定出栈序列判定是否合法消息队列面试题要点redis缓存击穿,失效以及热点keyag真人官方网的解决方案网页在浏览器上的渲染过程几种限流算法lru算法例题c/c 常见面试知识点总结附面试真题----20210529更新引入mq消息队列的作用及其优缺点mysql面试篇社招三年后端面试题60道测开面试题,背完直接涨工资二叉树的层序遍历(两种方法实现)bitmap 海量数据处理字符串倒序输出的五种方法c语言 输入10个数,统计出并输出正数、负数和0的个数字节三面:如何设计一个高并发系统架构,网络 面试36问,ddos攻击原理c 线程池使用 c 11 编写可复用多线程任务池lrucache结合any容器类型实现任意类型缓存c 实现lfu算法

lrucache结合any容器类型实现任意类型缓存-ag真人官方网

阅读 : 51

使用unordered_map 和 双向链表实现,支持设置缓存过期时间;

其中使用到的any.h 可查询我另一篇文章 任意类型容器


#ifndef _lru_h_
#define _lru_h_
#include 
#include 
#include 
#include "any.h"
template
class lrucache {
public:
    struct node {
        key     key;
        any     val;
        time_t  expire;
        node*   next;
        node*   prev;
        template
        void set(const key& k, const val& v, const int& e) {
            key = k;
            val = v;
            expire = e;
        }
        void init() {
            expire = 0;
            next = nullptr;
            prev = nullptr;
        }
    };
    explicit lrucache(const size_t& capacity = 100, bool pre_alloc = true): m_cap(capacity){
        m_head = nullptr;
        m_tail =  nullptr;
        if(pre_alloc) {
            m_available_node.resize(m_cap, nullptr);
            node* nodes = (node*)malloc(sizeof(node) * m_cap);
            m_allocated.push_back(nodes);
            for(int i = 0; i < m_cap; i  ) {
                m_available_node[i] = &nodes[i];
            }
        }
    }
    virtual ~lrucache(){
        for(void* mem : m_allocated) {
            free(mem);
        }
        m_allocated.clear();
    }
public:
    template
    void put(key key, val val, int expire = 0) {
        auto now = time(null);
        auto endtime = now   expire;
        if(expire == 0) {
            endtime = 0;
        }
        std::lock_guard guard(m_mutex);
        if(m_map.count(key)) {
            m_map[key]->val = val;
            m_map[key]->expire = endtime;
            deletenode(m_map[key]);
            inserthead(m_map[key]);
            return;
        }else if(m_map.size() >= cap()) {
            node* del = deletenode(m_tail);
            m_available_node.push_back(del);
        }else if(m_available_node.empty()) {
            size_t alloc_size = cap() - m_map.size();
            if(alloc_size > allocbatch) {
                alloc_size = allocbatch;
            }
            node* nodes = (node*)malloc(sizeof(node) * alloc_size);
            m_allocated.push_back(nodes);
            for(size_t i = 0; i < alloc_size; i  ) {
                m_available_node.push_back(&nodes[i]);
            }
        }
        node* node = m_available_node.back();
        m_available_node.pop_back();
        node->init();
        node->set(key, val, endtime);
        m_map[key] = node;
        inserthead(node);
        // 每次插入,都检查尾部节点是否已经过期, 如果过期则立即删除
        checktailexpire(now);
    }
    template
    bool get(key key, val& val) {
        std::lock_guard guard(m_mutex);
        if(!m_map.count(key)) {
            return false;
        }
        auto now = time(null);
        if(m_map[key]->expire != 0 && m_map[key]->expire < now) {
            node* del = deletenode(m_map[key]);
            m_available_node.push_back(del); 
            m_map.erase(key);
            return false;
        }
        val = m_map[key]->val.template any_cast();
        deletenode(m_map[key]);
        inserthead(m_map[key]);
        // 每次操作都检查一下尾部节点是否已经过期,过期则删除,通常认为尾节点可能会最先过期
        checktailexpire(now);
        return true;
    }
    bool delete(key key) {
        std::lock_guard guard(m_mutex);
        if(!m_map.count(key)) {
            return false;
        }
        deletenode(m_map[key]);
        m_available_node.push_back(m_map[key]);
        m_map.erase(key);
        return true;
    }
    const size_t& cap() const {
        return m_cap;
    }
    const size_t& size() const {
        std::lock_guard guard(m_mutex);
        return m_map.size();
    }
private:
    node* deletenode(node* node) {
        if(node->prev) {
            node->prev->next = node->next;
        }
        if(node->next) {
            node->next->prev = node->prev;
        }
        if(node == m_head) {
            m_head = node->next;
        }
        if(node == m_tail) {
            m_tail = node->prev;
        }
        return node;
    }
    void inserthead(node* node) {
        node->next = m_head;
        if(m_head) {
            m_head->prev = node;
        }
        node->prev = nullptr;
        m_head = node;
        if(m_tail == nullptr) {
            m_tail = node;
        }
    }
    void checktailexpire(const time_t& now) {
        if(m_tail && m_tail->expire < now) {
            node* del = deletenode(m_tail);
            m_available_node.push_back(del);
        }
    }
private:
    const size_t                    m_cap;
    std::unordered_map  m_map;
    struct node*                    m_head;
    struct node*                    m_tail;
    std::mutex                      m_mutex;
    std::vector              m_available_node;   // 可用的node节点池子,用于优化频繁的创建和释放node节点
    std::vector              m_allocated;        // 被分配的首地址
};
#endif
网站地图