Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms
CAS
bool compare_and_swap(int *addr, int oldval, int newval)
{
if( *addr != oldval ){
return false;
}
*addr = newval;
return true;
}
C++ CAS
template<class T >
boolatomic_compare_exchange_weak( std::atomic* obj,
T* expected, T desired );
template<class T >
boolatomic_compare_exchange_weak(volatile std::atomic* obj,
T* expected, T desired );
EnQueue
EnQueue(Q, data) //进队列
{
//准备新加入的结点数据
n = newnode();
n->value = data;
n->next = NULL;
do{
p = Q->tail; //取链表尾指针的快照
}while(CAS(p->next, NULL, n) != TRUE);
//while条件注释:如果没有把结点链在尾指针上,再试
CAS(Q->tail, p, n); //置尾结点 tail = n;
}
EnQueue(Q, data) //进队列改良版 v1
{
n = newnode();
n->value = data;
n->next = NULL;
p = Q->tail;
oldp = p
do{
while(p->next != NULL)
p = p->next;
}while(CAS(p.next, NULL, n) != TRUE); //如果没有把结点链在尾上,再试
CAS(Q->tail, oldp, n); //置尾结点
}
EnQueue(Q, data) //进队列改良版 v2
{
n = newnode();
n->value = data;
n->next = NULL;
while(TRUE){
//先取一下尾指针和尾指针的next
tail = Q->tail;
next = tail->next;
//如果尾指针已经被移动了,则重新开始
if( tail != Q->tail )continue;
//如果尾指针的 next 不为NULL,则 fetch 全局尾指针到next
if( next != NULL){
CAS(Q->tail, tail, next);
continue;
}
//如果加入结点成功,则退出
if(CAS(tail->next, next, n) == TRUE)break;
}
CAS(Q->tail, tail, n); //置尾结点
}
final
// https://mp.weixin.qq.com/s/0s3lDd4YdgqKUb-pQxYb2Q
// https://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html#nbq
InitQueue(Q)
{
node = newnode();
node->next = NULL;
Q->head = Q->tail = node; //初始化一个dummy结点
}
EnQueue(Q, data) //进队列改良版 v2
{
n = newnode();
n->value = data;
n->next = NULL;
while (TRUE)
{
//先取一下尾指针和尾指针的next
tail = Q->tail;
next = tail->next;
//如果尾指针已经被移动了,则重新开始
if (tail != Q->tail)
continue;
//如果尾指针的 next 不为NULL,则 fetch 全局尾指针到next
if (next != NULL)
{
CAS(Q->tail, tail, next);
continue;
}
//如果加入结点成功,则退出
if (CAS(tail->next, next, n) == TRUE)
break;
}
CAS(Q->tail, tail, n); //置尾结点
}
DeQueue(Q) //出队列,改进版
{
while (TRUE)
{
//取出头指针,尾指针,和第一个元素的指针
head = Q->head;
tail = Q->tail;
next = head->next;
// Q->head 指针已移动,重新取 head指针
if (head != Q->head)
continue;
if (head == tail)
{
if (next == NULL)
return ERR_EMPTY_QUEUE; // 如果是空队列
//如果 tail 指针落后了
CAS(Q->tail, tail, next);
continue;
}
//移动 head 指针成功后,取出数据
if (CAS(Q->head, head, next) == TRUE)
{
value = next->value;
break;
}
}
free(head); //释放老的dummy结点
return value;
}