设计 c++ web 框架时候,想要一个框架缓存类,很多通用缓存类是用字符保存,作为框架内置就不要序列和反序列了,因为框架内部使用。
想给自己的paozhu c++ web 框架添加缓存类,参考了springboot 于是确定用单例设计模式缓存类模板。
c++11后静态变量已经统一为线程安全了,网络各种茴香豆几种吃法现在变成一种安全吃法。
因为框架时候了多线程,也要求最低c++20,所以直接使用新标准单例模式。
因为需要保存多种类型,于是设计为模版接口,这样一个通用设计 缓存模型想好了,然后就是设计类库API,需要兼容数组和单一对象。
也要有超时,于是我们确定了基础结构
struct data_cache_t { std::vector<BASE_TYPE> data; unsigned int exptime = 0; };
因为我想以后还要动态库也能使用,于是用了一个静态函数做单例
template <typename BASETYPE_T> std::map<std::size_t, BASETYPE_T> &get_pz_cache() { static std::map<std::size_t, BASETYPE_T> instance; return instance; }
模版类需要兼顾数组和单个对象于是统一保存为vector数组,然后套入map对象,因为我们要用size_t做hash键值,这样方便统一长度。
然后根据不同api返回不同类型。
先看详细代码,后面讲一个map插入失败情况
template <typename BASE_TYPE> class pzcache { private: pzcache(){}; ~pzcache(){}; pzcache(const pzcache &); pzcache &operator=(const pzcache &); public: struct data_cache_t { std::vector<BASE_TYPE> data; unsigned int exptime = 0; }; public: void save(std::size_t hashid, BASE_TYPE &data_list, int expnum = 0, bool cover_data = false) { std::map<std::size_t, data_cache_t> &obj = get_pz_cache<data_cache_t>(); struct data_cache_t temp; temp.data.push_back(data_list); if (expnum != 0) { temp.exptime = http::timeid() + expnum; } else { temp.exptime = 0; } std::unique_lock<std::mutex> lock(editlock); auto [_, success] = obj.insert({hashid, temp}); if (!success) { if (cover_data) { obj[hashid] = temp; } else { obj[hashid].exptime = temp.exptime; } } } void save(std::size_t hashid, std::vector<BASE_TYPE> &data_list, int expnum = 0, bool cover_data = false) { std::map<std::size_t, data_cache_t> &obj = get_pz_cache<data_cache_t>(); struct data_cache_t temp; temp.data = data_list; if (expnum != 0) { temp.exptime = http::timeid() + expnum; } else { temp.exptime = 0; } std::unique_lock<std::mutex> lock(editlock); auto [_, success] = obj.insert({hashid, temp}); if (!success) { if (cover_data) { obj[hashid] = temp; } else { obj[hashid].exptime = temp.exptime; } } } bool remove(std::size_t hashid) { std::map<std::size_t, data_cache_t> &obj = get_pz_cache<data_cache_t>(); std::unique_lock<std::mutex> lock(editlock); auto iter = obj.find(hashid); if (iter != obj.end()) { obj.erase(iter++); return true; } return false; } void remove_exptime() { std::map<std::size_t, data_cache_t> &obj = get_pz_cache<data_cache_t>(); unsigned int nowtime = http::timeid(); std::unique_lock<std::mutex> lock(editlock); for (auto iter = obj.begin(); iter != obj.end();) { if (iter->second.exptime == 0) { continue; } if (iter->second.exptime < nowtime) { obj.erase(iter++); } } } void clear() { std::map<std::size_t, data_cache_t> &obj = get_pz_cache<data_cache_t>(); std::unique_lock<std::mutex> lock(editlock); obj.clear(); } int check(std::size_t hashid) { std::map<std::size_t, data_cache_t> &obj = get_pz_cache<data_cache_t>(); unsigned int nowtime = http::timeid(); std::unique_lock<std::mutex> lock(editlock); auto iter = obj.find(hashid); if (iter != obj.end()) { if (iter->second.exptime