- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
设计 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 == 0) { return 0; } int temp = (int)(iter->second.exptime - nowtime); if (temp == -1) { return -2; } return temp; } return -1; } int update(std::size_t hashid, int exptime = 0) { std::map<std::size_t, data_cache_t> &obj = get_pz_cache<data_cache_t>(); unsigned int nowtime = http::timeid() + exptime; if (exptime == 0) { nowtime = 0; } std::unique_lock<std::mutex> lock(editlock); auto iter = obj.find(hashid); if (iter != obj.end()) { if (iter->second.exptime == 0) { iter->second.exptime = nowtime; return 0; } iter->second.exptime = nowtime; return 1; } return -1; } std::vector<BASE_TYPE> get_array(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 == 0) { return iter->second.data; } if (iter->second.exptime >= nowtime) { return iter->second.data; } else { obj.erase(iter++); } } lock.unlock(); std::vector<BASE_TYPE> temp; return temp; } BASE_TYPE get(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 == 0) { if (iter->second.data.size() > 0) { return iter->second.data[0]; } } if (iter->second.exptime >= nowtime) { if (iter->second.data.size() > 0) { return iter->second.data[0]; } } else { obj.erase(iter++); } } lock.unlock(); BASE_TYPE temp; return temp; } static pzcache &conn() { static pzcache instance; return instance; } public: std::mutex editlock; };
。
auto [_, success] = obj.insert({hashid, temp}),
这个map insert 方法如果存在会插入失败,于是我用API指定是更新过期时间或删除重新添加,这一步巧妙利用了map这个特性,需要c++17以上.
。
然后使用方式就是很简单了 。
。
pzcache<std::string> &temp_cache = pzcache<std::string>::conn();
。
我们缓存一个string 对象,首先取得单例.
pzcache<std::string> &temp_cache = pzcache<std::string>::conn();
std::string namestring = "testname"; std::size_t cache_hashid = std::hash<std::string>{}(namestring); if (temp_cache.check(cache_hashid) > -1) { client << " 已经存在,不需要再存 "; } else { std::string cache_data = "This cache content!"; temp_cache.save(cache_hashid, cache_data, 30); client << "缓存新的内容"; }
。
然后我们在其它线程使用 。
pzcache<std::string> &temp_cache = pzcache<std::string>::conn(); std::string namestring = "testname"; std::size_t cache_hashid = std::hash<std::string>{}(namestring); std::string cache_data = temp_cache.get(cache_hashid);
是不是很简单,c++ 强大的模板能力,一个通用类库设计好了,而且简单好用 。
。
欢迎使用 国产 C++ web 框架 paozhu 1.2.0 发布 。
源代码里面更多的设计模式可以参考,框架LICENSE反正为MIT模式,大家商用也没有问题.
https://github.com/hggq/paozhu 。
最后此篇关于c++程序通用多线程单例设计c++web框架设计经验谈的文章就讲到这里了,如果你想了解更多关于c++程序通用多线程单例设计c++web框架设计经验谈的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!