C++ Boost atomic:具有大量数据的无等待环形缓冲区

C++ Boost atomic:具有大量数据的无等待环形缓冲区,c++,boost,atomic,circular-buffer,C++,Boost,Atomic,Circular Buffer,我想使用boost::atomic作为无等待环形缓冲区,如下所述: 我的producer同时提供大量数据(无符号字符,+-3000个值),就像一个矩阵一样,它会逐行填充。将这些值推送到缓冲区的最佳方法是什么?我应该在它们上面循环还是可以在它们内部循环 如果我想同时读取一组值,pop也是如此 这就是我想到的,有什么理由不好吗? 我只需要确保RINGBUFFERSIZE%iSize=0 #define RINGBUFFERSIZE = 30000 ring_[RINGBUFFERSIZE];

我想使用
boost::atomic
作为无等待环形缓冲区,如下所述:

我的
producer
同时提供大量数据(无符号字符,+-3000个值),就像一个矩阵一样,它会逐行填充。将这些值推送到缓冲区的最佳方法是什么?我应该在它们上面循环还是可以在它们内部循环

如果我想同时读取一组值,
pop
也是如此


这就是我想到的,有什么理由不好吗? 我只需要确保
RINGBUFFERSIZE%iSize=0

#define RINGBUFFERSIZE = 30000

ring_[RINGBUFFERSIZE];

bool push(unsigned char* iData, int iSize)
{
    size_t head = head_.load(boost::memory_order_relaxed);
    size_t next_head = next(head,iSize);
    if (next_head == tail_.load(boost::memory_order_acquire))
    return false;
    memcpy(ring_+head,iData,iSize);
    head_.store(next_head, boost::memory_order_release);
}

bool pop(unsigned char * value, int iSize)
{
     size_t tail = tail_.load(boost::memory_order_relaxed);
     if (tail == head_.load(boost::memory_order_acquire))
         return false;
     value = &ring_[tail];
     tail_.store(next(tail,iSize), boost::memory_order_release);
     return true;
}


size_t next(size_t current, int iSize)
{
     return (current + iSize) % RINGBUFFERSIZE;
}

最快的方法是将指针(无论是
无符号字符*
还是指向包含长度的某个结构的指针)推入

当然,假设可以强制
pop
获取与推送的数据块完全相同的数据块,这就解决了问题:现在您必须以某种方式管理这些缓冲区的分配


管理区块的简单示例解决方案:

  • 预先分配“足够”的固定大小的块对象(比如动态长度+
    无符号字符数据[3096]
    或其他)
  • 发送无等待环形缓冲区中块的地址
  • 当使用者处理完地址后,将其发送回另一个环形缓冲区,以便生产者可以回收相同的区块对象


  • 如果你真的不能做到这一点,你可以为你的块选择一个最大大小,并按值推/弹出该大小的对象。。。但老实说,这似乎非常浪费(即使对象知道它的长度,所以不必
    memcpy
    整个3k数组来获得较小的块)。

    最快的方法是推送一个指针(或者
    无符号字符*
    或者指向包含长度的某个结构的指针)

    当然,假设可以强制
    pop
    获取与推送的数据块完全相同的数据块,这就解决了问题:现在您必须以某种方式管理这些缓冲区的分配


    管理区块的简单示例解决方案:

  • 预先分配“足够”的固定大小的块对象(比如动态长度+
    无符号字符数据[3096]
    或其他)
  • 发送无等待环形缓冲区中块的地址
  • 当使用者处理完地址后,将其发送回另一个环形缓冲区,以便生产者可以回收相同的区块对象


  • 如果你真的不能做到这一点,你可以为你的块选择一个最大大小,并按值推/弹出该大小的对象。。。但老实说,这似乎非常浪费(即使对象知道它的长度,所以不必
    memcpy
    整个3k数组来存储较小的块)。

    确切地说,指向的内存将不再有效,所以我需要复制数据本身。当然,您可以控制缓冲区的有效性吗?数据来自tcp连接,所以每次读取我都需要存储它。是的,但是你读取到的内存的分配和生命周期管理是在你的控制之下。。。除非您特别关注重新组装部分读取?您当然可以这样做,但我认为使用这个容器(它面向离散值对象,而不是可变长度数据流)并不容易。确切地说,指向的内存将不再有效,所以我需要复制数据本身。当然你可以控制缓冲区的有效性吗?数据来自tcp连接,所以每次读取时我都需要存储数据。是的,但是你读取到的内存的分配和生命周期管理由你控制。。。除非您特别关注的是重新组装部分读取?您当然可以这样做,但我认为使用这个容器(面向离散值对象而不是可变长度数据流)并不容易。建议的解决方案不太有效,因为
    next\u head
    可能已经结束。在这种情况下,您没有一个连续的块,也不能执行单个
    memcpy
    (当然,您可以检查这种情况,也可以执行两个)。建议的解决方案不太有效,因为
    next\u head
    可能已经结束。在这种情况下,您没有一个连续的块,无法执行单个
    memcpy
    (当然,您可以检查这种情况,也可以执行两个)。