1、readerwriterqueue C++单生产者,单消费者无锁队列,它只支持两个线程用例,一个用于生产,一个用于消费
github地址:https://github.com/cameron314/readerwriterqueue
2、优点
快速
兼容C++11标准
就像 std::queue
一样,你不需要为元素分配内存
在连续块中预先分配内存
提供一种try_enqueue
保证永不分配内存的方法(队列以初始容量开始)
还提供了enqueue
一种可以根据需要动态增加队列大小的方法
等等
3、使用
将atomicops.h文件和readerwriterqueue.h文件放在项目中去,使用的时候需要#include "readerwriterqueue.h"就可以了
具体的几个函数介绍如下
enqeue:入队
try_enqueue:入队,如果队列空间不够返回false
try_dequeue:出队,如果队列为空返回false
size_approx():当前队列的大小
max_capacity():当前队列的最大容量,会动态变化的
pop():从队列中删除最前面的一个元素
另外还有一个阻塞版本的(BlockReaderWriterQueue),阻塞版本接口和非阻塞版本(ReaderWriterQueue)接口基本一样,并新增了wait_dequeue()和wait_dequeue_timed()两个函数
具体使用例子如下
#include <iostream>
#include "readerwriterqueue.h"
using namespace moodycamel;
int main(void){
// 预先分配内存
ReaderWriterQueue<int> q(10);
// 数据进队
for(int i=1;i<=11;++i){
q.enqeue(i);
}
// 打印大小
std::cout << q.size_approx() << std::endl;
// 出队
// try_dequeue成功返回true,失败返回false,表示没有拿到数据
int val;
while(q.size_approx()){
q.try_dequeue(val);
std::cout << "val:" << val << std::endl;
}
if(!q.try_dequeue(val)){
std::cout << "no value" << std::endl;
}
return 0;
}
接下来会使用两个线程,一个线程往队列中写数据,一个线程从队列中读数据
#include <chrono>
#include <iostream>
#include <thread>
#include "readerwriterqueue.h"
using namespace moodycamel;
int main(void) {
// 两个线程,一个线程写数据一个线程读数据
// 预先分配内存
ReaderWriterQueue<int> q(10);
std::cout << q.max_capacity() << std::endl;
int val = 1;
std::thread writer([&]() {
while (true) {
q.enqueue(val++);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
});
std::thread reader([&]() {
int tmp;
while (true) {
if (!q.try_dequeue(tmp)) {
continue;
}
std::cout << tmp << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
});
writer.join();
reader.join();
return 0;
}