关于无锁队列的实现,网上有很多的文章,其实现原理都来自论文implementing_lock_free.pdf,国内关于无锁队列实现介绍的较好的博客:http://coolshell.cn/articles/8239.html
关于理论的介绍上述文章已经写的非常好了,因此本文不会复述无锁队列实现原理,只讲解下实现细节以及过程中遇到的问题。
本文实现的是一个多生产者多消费者无锁队列,相比于单生产者多消费者等要复杂很多。
实现代码:
#define dqix_atomic_cmp_set(lock, set, old) \
( (LONG) InterlockedCompareExchange( (LONG *)lock, (LONG)set, (LONG)old ) \
== (LONG)old )
#define dqix_atomic_fetch_add( p, add ) InterlockedExchangeAdd( (LONG *)p, add )
#define dqix_atomic_increase( p ) InterlockedExchangeAdd( (LONG *)p, 1 )
#define dqix_atomic_decrease( p ) InterlockedExchangeAdd( (LONG *)p, -1 )
#pragma intrinsic(_ReadWriteBarrier)
#define dqix_memory_barrier() _ReadWriteBarrier()
template class FreeList;
template
struct GenericNode
{
GenericNode( FreeList * free_ls = NULL )
:ref_cnt(0), next(NULL), _free_list(free_ls){}
~GenericNode(){}
inline void init( ) volatile
{
ref_cnt = 1;
next = NULL;
}
inline volatile GenericNode* add_ref( ) volatile
{
for( int cnt = ref_cnt; cnt > 0; cnt = ref_cnt ){
if ( dqix_atomic_cmp_set( &ref_cnt, cnt + 1, cnt ) ){
return this;
}
}
return NULL;
}
inline void release_ref( )volatile
{
if( dqix_atomic_decrease( &ref_cnt ) == 1 ){
if ( _free_list ){
_free_list->release( this );
return;
}
delete this;
}
}
inline int ref_count() volatile
{
return ref_cnt;
}
T value;
volatile GenericNode* volatile next;
private:
volatile int ref_cnt;
FreeList *_free_list;
};
template
class FreeList
{
public:
typedef GenericNode Node;
typedef volatile Node* volatile AtomicNodePtr;
FreeList( size_t capacity = 100 ): _head(0), _tail(0), _capacity(capacity),_size(0), nil((void*)-1)
{
_head = new(std::nothrow) Node(this);
_head->next = (AtomicNodePtr)nil;
_tail = _head;
}
~FreeList(){}
AtomicNodePtr allocate() volatile
{
if ( _head == NULL ){
set_dqix_error( EDQIX_MEMFAIL );
return NULL;
}
for( ;; ){
AtomicNodePtr p = _head;
AtomicNodePtr pnext = _head->next;
if ( _head == _tail ){
p = new(std::nothrow) Node((FreeList*)this);
if ( !p ){
set_dqix_error( EDQIX_MEMFAIL );
return NULL;
}
p->init();
return p;
}
if ( dqix_atomic_cmp_set( &_head, p->next, p )){
if ( p->ref_count() == 0 ){
p->init();
dqix_atomic_decrease(&_size);
return p;
}
_CrtDbgBreak();
}
}
}
void release( volatile Node* volatile node ) volatile
{
if ( _size >= _capacity ){
delete node;
return;
}
node->next = ( AtomicNodePtr )nil;
memset( (void*)&(node->value), 0, sizeof(node->value) );
for (;;){
AtomicNodePtr old = _tail;
if ( dqix_atomic_cmp_set( &(old->next), node, nil ) ){
if( !dqix_atomic_cmp_set( &_tail, node, old ) ){
_CrtDbgBreak();
}
dqix_atomic_increase(&_size);
return;
}
}
}
private:
AtomicNodePtr _head;
AtomicNodePtr _tail;
volatile size_t _capacity;
volatile int64_t _size;
const void *nil;
};
template
class Queue
{
public:
Queue()
:_head(NULL), _tail(NULL), _size(0){}
~Queue()
{
volatile Node *p = _head->next;
for( ; p; p = _head->next ){
_head->next = p->next;
delete p;
}
delete _head;
}
bool push( const T& value )
{
if( _head == NULL ){
_head = _pool.allocate();
if( !_head ){
set_dqix_error( EDQIX_MEMFAIL );
return false;
}
_tail = _head;
}
AtomicNodePtr new_node = _pool.allocate();
if( !new_node ){
set_dqix_error( EDQIX_MEMFAIL );
return false;
}
new_node->value = value;
dqix_memory_barrier();
for( ;; ){
AtomicNodePtr p = _tail;
if( !p->next && dqix_atomic_cmp_set( &(p->next), new_node, NULL ) ){
if( !dqix_atomic_cmp_set( &_tail, new_node, p ) ){
_CrtDbgBreak();
}
dqix_atomic_increase( &_size );
return true;
}
}
}
bool pop( T& value )
{
if( !_head || !_head->next ){
set_dqix_error( EDQIX_QUEUE_EMPTY );
return false;
}
for( ;; ){
AtomicNodePtr p = _head->add_ref();
if( !p ){
continue;
}
if( p == _tail ){
set_dqix_error( EDQIX_QUEUE_EMPTY );
p->release_ref( );
return false;
}
AtomicNodePtr pnext = p->next;
if ( p != _head || !pnext->add_ref() ){
p->release_ref( );
continue;
}
if( dqix_atomic_cmp_set( &_head, p->next, p ) ){
value = pnext->value;
pnext->release_ref();
p->release_ref();//release _head->add_ref()增加的引用
p->release_ref();//release 自身的引用,释放指针p
dqix_atomic_decrease( &_size );
return true;
}
p->release_ref();
pnext->release_ref();
}
}
bool empty() const{ return _size == 0; }
size_t size() const { return _size; }
private:
typedef GenericNode Node;
typedef volatile Node* volatile AtomicNodePtr;
AtomicNodePtr _head;
AtomicNodePtr _tail;
volatile int _size;
volatile FreeList _pool;
};
代码主要由GenericNode,FreeList, Queue组成,下面分别对其进行说明。