C++ 线程安全队列,因项目开发需要,进行了设计,并记录,
代码已收录在:C++跨平台轻量组件库大全-json-base64-url-安全队列等
支持的功能
1、支持多线程。
2、等待数据超时。
3、最大队列长度设置。
入列时候,检查长度,过长则清空后再入列。
出列时候,不检查长度。
4、c++跨平台。
5、新数据到来及时通知等待数据的线程。
6、先进先出。
使用到的 c++ stl 标准库:
1、mutex :用于线程锁。
2、queue: 队列。
3、condition_variable:条件变量,用于等待和通知。类似windows事件。
4、thread:线程和睡眠。
5、sstream:格式化字符串。
6、string:字符串。
多线程队列设计
封装了一个模板类myque. 即提供:
构造函数:
myque(); // 默认构造。
myque(unsigned long maxquelen); // 带最大队列长度的构造。
成员方法:入列和出列。
bool pop(ty &v, unsigned long wait_timeout_ms); // 出列。
void push(const ty &v); // 入列。
文件 myque.hpp 源码如下:
#ifndef _MYQUE_20210423_
#define _MYQUE_20210423_
#include <queue>
#include <mutex>
#include <condition_variable>
template <typename ty>
class myque : public std::queue<ty> {
typedef std::queue<ty> mysuper;
public:
myque() { m_maxquelen = ~0; }
myque(unsigned long maxquelen) { m_maxquelen = maxquelen; }
public:
// 出队列,并从队列移除数据。
bool pop(ty &v, unsigned long wait_timeout_ms) {
std::unique_lock<std::mutex> lock(m_mtx);
if (false == waitdata(lock, wait_timeout_ms))
return false;
v = mysuper::front();
mysuper::pop();
return true;
}
// 入队列
void push(const ty &v) {
{
std::unique_lock<std::mutex> lock(m_mtx);
if (mysuper::size() > m_maxquelen) {
myque<ty>().swap(*this);
}
mysuper::push(v);
}
m_cv.notify_all(); // 新数据,并通知wait_for。
return;
}
private:
bool waitdata(std::unique_lock<std::mutex> &lock, unsigned long wait_timeout_ms) {
if (false == mysuper::empty())
return true; // 如果有数据,不等待,返回。
// 如果不需要等待,直接返回。
if (0 == wait_timeout_ms)
return false;
// 等待,如果有数据,则立即返回,否则直到超时。
// 等待过程会释放锁,等待结束会重新上锁。
m_cv.wait_for(lock, std::chrono::milliseconds(wait_timeout_ms));
if (false == mysuper::empty())
return true; // 等待后有数据。
// 等待后没有数据。
return false;
}
private:
std::mutex m_mtx; // 互斥锁.
std::condition_variable m_cv; // 条件变量.
unsigned long m_maxquelen;
};
#endif
使用方式
文件main.cpp引入myque.hpp, 并启动线程进行读写:
#include <string>
#include <thread>
#include <iostream>
#include <sstream>
#include "myque.hpp"
myque<std::string> g_que(500);
void threadProcessData() {
int count = 0;
while (true) {
std::string str;
std::stringstream strfmt;
strfmt << "loop count: " << count++ << ". " ;
// 等待数据出列。
if (g_que.pop(str, 5000)) {
strfmt << "new data: " << str << std::ends;
} else {
strfmt << "5000 ms time out. " << std::ends;
}
std::cout << strfmt.str() << std::endl;
}
}
void threadAddData() {
while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
// 入列数据
g_que.push("123");
}
}
int main()
{
// 启动一个线程处理数据
std::thread(threadProcessData).detach();
// 启动10个线程添加数据
for (size_t i = 0; i < 10; i++) {
std::thread(threadAddData).detach();
}
// main流程持续等待。
while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}