C++ 如何控制无锁环形缓冲区中的读/写指针?
我刚刚编写了一个无锁的环缓冲区dem,但在多读线程的情况下工作失败。在我的代码中,读和写指针是递增的。我不能保证读指针总是在写指针之后 这是我的put/get函数:C++ 如何控制无锁环形缓冲区中的读/写指针?,c++,c++11,atomic,C++,C++11,Atomic,我刚刚编写了一个无锁的环缓冲区dem,但在多读线程的情况下工作失败。在我的代码中,读和写指针是递增的。我不能保证读指针总是在写指针之后 这是我的put/get函数: template<class T> bool RingBuffer<T>::put( const T& node ) { // local the avaliable place while ( full() ) { if ( !waitForFull() ) retu
template<class T>
bool RingBuffer<T>::put( const T& node )
{
// local the avaliable place
while ( full() ) {
if ( !waitForFull() ) return false;
}
::std::size_t pos = m_front.fetch_add(1);
while( !__sync_bool_compare_and_swap( &m_statusBuffer[ locate(pos) ], NS_WRITEABLE, NS_WRITEPENDING ) ) {
if ( m_statusBuffer[ locate(pos) ] == NS_READPENDING ) {
// wait for read complete
continue;
}
while ( full() ) {
if ( !waitForFull() ) return false;
}
pos = m_front.fetch_add(1);
}
fprintf( stderr, "put pos: %ld, front: %ld, rear: %ld\n", pos, m_front.load(), m_rear.load() );
// update data
m_circularBuffer[ locate(pos) ] = node;
m_statusBuffer[ locate(pos) ] = NS_READABLE;
return true;
}
template<class T>
::std::tuple<T, bool> RingBuffer<T>::get()
{
while ( empty() ) {
if ( !waitForEmpty() ) return ::std::make_tuple( T(), false );
}
// local the avaliable place
::std::size_t pos = m_rear.fetch_add(1);
while( !__sync_bool_compare_and_swap( &m_statusBuffer[ locate(pos) ], NS_READABLE, NS_READPENDING ) ) {
if ( m_statusBuffer[ locate(pos) ] == NS_WRITEPENDING ) {
// wait for write complete
continue;
}
while ( empty() ) {
if ( !waitForEmpty() ) return ::std::make_tuple( T(), false );
}
pos = m_rear.fetch_add(1);
}
fprintf( stderr, "get pos: %zd, front: %ld, rear: %ld\n", pos, m_front.load(), m_rear.load() );
// update value
auto ret = m_circularBuffer[ locate(pos) ];
m_statusBuffer[ locate(pos) ] = NS_WRITEABLE;
return ::std::make_tuple( ret, true );
}
模板
bool-RingBuffer::put(常量T和节点)
{
//可利用的地方
while(full()){
如果(!waitForFull())返回false;
}
:std::size\u t pos=m\u front.fetch\u add(1);
while(!\u同步\u bool\u比较\u和\u交换(&m\u statusBuffer[locate(pos)],NS\u可写,NS\u可写)){
如果(m_statusBuffer[locate(pos)]==NS_READPENDING){
//等待读取完成
继续;
}
while(full()){
如果(!waitForFull())返回false;
}
pos=m_front.fetch_add(1);
}
fprintf(标准,“放置位置:%ld,前部:%ld,后部:%ld\n”,位置,m_-front.load(),m_-rear.load());
//更新数据
m_circularBuffer[locate(pos)]=节点;
m_statusBuffer[locate(pos)]=NS_可读;
返回true;
}
模板
::std::tuple RingBuffer::get()
{
while(empty()){
if(!waitForEmpty())返回::std::make_tuple(T(),false);
}
//可利用的地方
::std::size\u t pos=m\u-rear.fetch\u-add(1);
while(!\u同步\u bool\u比较\u和\u交换(&m\u statusBuffer[locate(pos)],NS\u可读,NS\u READPENDING)){
如果(m_statusBuffer[locate(pos)]==NS_WRITEPENDING){
//等待写入完成
继续;
}
while(empty()){
if(!waitForEmpty())返回::std::make_tuple(T(),false);
}
pos=m_后方。取_添加(1);
}
fprintf(stderr,“获取位置:%zd,前面:%ld,后面:%ld\n”,位置,m_front.load(),m_rear.load());
//更新值
自动返回=m_循环缓冲[定位(位置)];
m_statusBuffer[locate(pos)]=NS_可写;
return::std::make_tuple(ret,true);
}
空/满是:
template<class T>
bool RingBuffer<T>::empty()
{
return ( m_rear.load() >= m_front.load() );
}
template<class T>
bool RingBuffer<T>::full()
{
//return ( ( m_front.load() >= m_rear.load() && ( m_front.load() - m_rear.load() ) >= m_mask ) );
return ( m_front.load() - m_rear.load() ) >= m_mask );
}
模板
bool-RingBuffer::empty()
{
返回(m_后.load()>=m_前.load());
}
模板
bool-RingBuffer::full()
{
//返回((m_front.load()>=m_rear.load()&&&(m_front.load()-m_rear.load())>=m_mask));
返回(m_front.load()-m_reast.load())>=m_mask);
}
当我使用多线程时,读指针将跨过写指针,然后阻塞或核心转储
如何修复此错误?在无锁环形缓冲区中,可以在写入程序和读取程序之间进行同步。这通常是通过比较写指针和读指针(或索引)来实现的,而只有编写器可以更改写指针,而读取器只能更改读指针。您计划使用什么机制使多个读卡器与无锁访问同步?我会说这个概念很奇怪,或者至少不清楚。我为多个编写者同时编写添加了一个额外的状态buff,这也会影响读取操作。但是它带来了很多错误。谢谢你的回答。我会尝试完全分离读者和作者。将
std::atomic
与遗留\u sync
内置软件混合使用应该是不必要的。我建议从最好的例子中学习。