Я просто пишу безблокировочный демон ringbuffer, но работа не удалась с многопоточными потоками. В моем коде указатели чтения и записи увеличиваются. Я не могу гарантировать, что указатель чтения всегда будет после указателя записи.
Это моя функция put / get:
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 );
}
и пустое / полное значение:
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 );
}
Когда я использую многопоточность, указатель чтения перешагнет указатель записи, а затем заблокирует или сбросит память.
Как я могу исправить эту ошибку?