您好我已经计划使用boost SPSC队列。我必须有一个监听器,它总是在收到消息时监听传入消息,将消息放入队列并返回等待新消息。还有一个消费者从队列中弹出消息并对其进行处理。
由于我不希望我的监听器等待锁定写入队列,我更喜欢boost_lockfree_spsc_queue
。我相信如果我在初始化队列时设置fixed_sized<false>
,队列的大小会有所不同。但似乎不是。
以下是我的代码:
boost::lockfree::spsc_queue<int, boost::lockfree::fixed_sized<false>> lockFreeQ{10};
void sharedQueue::lockFreeProduce()
{
for(int i = 0; i < 100; i++)
{
lockFreeQ.push(i);
cout<<"--"<<i<<endl;
}
}
void sharedQueue::lockFreeConsume(){
for(int i = 0; i <100; i++){
/* Implement a blocking pop to the queue in order to waste cpu time by busy waiting*/
while(!(lockFreeQ.read_available() > 0))
{
//std::this_thread::yield();
std::this_thread::sleep_for(std::chrono::nanoseconds(10));
}
cout<<" ***"<<lockFreeQ.front()<<endl;
lockFreeQ.pop();
}
}
void sharedQueue:: TestLockFreeQueue()
{
std::thread t1([this]() { this->lockFreeProduce(); });
std::thread t2([this]() { this->lockFreeConsume(); });
t1.join();
t2.join();
}
输出显示数据丢失。以下是部分结果。但它错过了87号,92号。
**85
***86
***88
***90
***91
***93
***95
***96
***98
如果它是可变大小的,它应该扩展队列的大小,不应该丢失数据。它似乎覆盖了A consequence of the circular buffer is that when it is full and a subsequent write is performed, then it starts overwriting the oldest data.所解释的数据。在这种情况下,如何在不丢失数据的情况下处理这个问题?
谢谢
答案 0 :(得分:0)
翻译评论以回答。
政策适用于spsc_queue
的方式如下:
typedef typename mpl::if_c<runtime_sized,
runtime_sized_ringbuffer<T, allocator>,
compile_time_sized_ringbuffer<T, capacity>
>::type ringbuffer_type;
在您的情况下,它会选择runtime_sized_ringbuffer
缓冲区而不是compile_time_sized_ringbuffer
。
两者之间的区别是,在runtime_sized_ringbuffer
的情况下,使用作为模板参数传递的allocator
来分配大小数组(作为参数传递给构造函数) / em>在compile_time_sized_ringbuffer
的情况下,数组在堆栈上分配。
因此,如果您的队列规模很大,则必须使用runtime_sized_ringbuffer
代替compile_time_sized_ringbuffer
。
这是唯一的区别,在这两种情况下,基础数据结构都是circular_buffer
。即使在runtime_sized_ringbuffer
的情况下,一旦完成写入缓冲区中的所有位置/索引,最旧的元素将被覆盖。从下面的代码中可以看出这是非常直接的
static size_t next_index(size_t arg, size_t max_size)
{
size_t ret = arg + 1;
while (unlikely(ret >= max_size))
ret -= max_size;
return ret;
}
如果你真的需要一个无锁列表数据结构,你应该按Dmitry Vyukov
查看着名的无锁列表数据结构