c++无锁队列

2023-02-02  本文已影响0人  谭英智

单生产单消费

ring buffer

多生产多消费

链表+CAS

生产消息

void Enqueue(x):
  auto q = new record();
  q->value = x;
  q->next = null;
  auto p = tail;
  auto null_ptr = null;
  do{
    while (p->next != null)
      p = next;
    null_ptr = null;
  } while(!p->next.compare_exchange_weak(null_ptr, q));

  auto cur = p;
  do{
    p = cur;
  } while(!tail.compare_exchange_weak(p, q);

消费消息

record Dequeue(){
  auto p = head;
  do{
    p = head;
    if(p == null) {
        return -1;
    }
  }while(!head.compare_exchange_weak(p, p.next);
  return p->value;
}

使用链表,会使得访问消息队列cache不亲和

disruptor(ring buffer+CAS)

生产消息

lock-free-queue-disruptor-write
long tryReserveWrite(int n)
{
    if (n < 1)
    {
        return -1;
    }
 
    long current;
    long next;
 
    do
    {
        current = cursor.get();
        next = current + n;
 
        if (!hasAvailableCapacity(gatingSequences, n, current))
        {
            return -1;
        }
    }
    while (!cursor.compare_exchange_weak(current, next));
 
    return next;
}

消费消息

lock-free-queue-disruptor-read
long tryReserveRead(int n)
{
    if (n < 1)
    {
        return -1;
    }
 
    long current;
    long next;
 
    do
    {
        current = reader_cursor.get();
        next = current + n;
 
        if (!checkReadAvailable(gatingSequences, n, current))
        {
            return -1;
        }
    }
    while (!reader_cursor.compare_exchange_weak(current, next));
 
    return next;
}

使用数组,会让消息队列cache更加亲和

为了避免伪共享,需要把每个原子变量都align cache line的大小

上一篇下一篇

猜你喜欢

热点阅读