2013-09-27 83 views
4

我正在C++中进行多线程编程,我在想C++中是否有线程安全的环形缓冲区实现,或者您是否知道如何实现它。C++ threadsafe环缓冲区实现

+0

也许http://stackoverflow.com/questions/9743605/thread-safe-循环缓冲的实现回答你的问题 – villekulla

+1

当只有一个线程写入另一个线程读取时,你在寻找特殊情况吗?或者你想要一个通用的解决方案? – paddy

+1

实现任何线程安全容器相对容易,除非性能是您的驱动因素。你究竟在寻找什么? – Chad

回答

-1

这是一个基本的实现。要求存储在缓冲区中的对象是默认可构造的,并且是可复制的(通过将它们存储在std :: vector <>中)。需要C++11支持(对于std::atomic)。几乎所有最近gcc版本将具有它与-std=c++11-std=c++0x

如果c++11不可用,用正确的编译器的内部制作head_tail_原子。

对于一个阅读器线程和一个写入器线程应该是安全的。通过调用

auto val = ringbuffer.back(); 
    val = some_value; 
    ringbuffer.push(); 

Retreive项目:

通过调用发布项目

auto val = ringbuffer.front(); 
    // do stuff with val 
    ringbuffer.pop(); 

如果back()回报nullptr,那么缓冲区 “满”。如果front()返回nullptr那么缓冲区是“空的”。

警告,未测试(全部):d

#include <vector> 

    template <class T> 
    class RingBuffer 
    { 
    public: 
    RingBuffer(size_t buffer_size) 
     : ring_(buffer_size) 
     , buffer_size_(buffer_size) 
     , head_(0) 
     , tail_(0) 
    { 
    } 

    T* back() 
    { 
     bool received = false; 

     if(available(head_, tail_)) 
     { 
      return &(ring_[head_ % buffer_size_]); 
     } 

     return nullptr; 
    } 

    void push() 
    { 
     ++head_; 
    } 

    T* front() 
    { 
     if(tail_ < head_) 
     { 
      return & ring_[tail_ % buffer_size_]; 
     } 

     return nullptr; 
    } 

    void pop() 
    { 
     ++tail_; 
    } 

    size_t size() const 
    { 
     if(tail_ < head_) 
      return buffer_size_ - ((tail_ + buffer_size_) - head_); 
     else if(tail_ > head_) 
      return buffer_size_ - (tail_ - head_); 

     return 0; 
    } 

    bool available() 
    { 
     return available(head_, tail_); 
    } 

    private: 
    bool available(uint64_t h, uint64_t t) const 
    { 
     if(h == t) 
      return true; 
     else if(t > h) 
      return (t - h) > buffer_size_; 
     else// if(h > t) 
      return (t + buffer_size_) - h > 0; 
    } 

    std::vector<T> ring_; 
    const size_t buffer_size_; 
    std::atomic<uint64_t> head_; 
    std::atomic<uint64_t> tail_; 
    }; 
+0

我不明白你的意思是“如果C++ 11 isn不可用,用适当的编译器内部函数来替代head_和tail_atomic。“ –

+0

'head_'和'tail_'必须是原子的,这意味着修改(或读取它们的值)应该是原子操作。如果你不明白这意味着什么,那么我认为你可能没有准备好多线程编程。 – Chad

+0

嗯。不知道我得到这个。是不是'size'容易受到另一个线程调用'push'的影响,并且在'if'和'return'之间改变'head_'的值? – Tom