簡體   English   中英

循環緩沖區的線程安全實現

[英]Thread safe implementation of circular buffer

boost 庫中的 Circular_buffer 不是線程安全的。 所以我將 boost::circular_buffer 對象包裝在一個類中,如下所示。 線程之間的互斥是通過使用條件變量、互斥鎖和鎖獲取/釋放來實現的(我認為)。 這個實現線程安全嗎?

#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/circular_buffer.hpp>

// Thread safe circular buffer 
template <typename T>
class circ_buffer : private boost::noncopyable
{
public:
    typedef boost::mutex::scoped_lock lock;
    circ_buffer() {}
    circ_buffer(int n) {cb.set_capacity(n);}
    void send (T imdata) {
        lock lk(monitor);
        cb.push_back(imdata);
        buffer_not_empty.notify_one();
    }
    T receive() {
        lock lk(monitor);
        while (cb.empty())
            buffer_not_empty.wait(lk);
        T imdata = cb.front();
        cb.pop_front();
        return imdata;
    }
    void clear() {
        lock lk(monitor);
        cb.clear();
    }
    int size() {
        lock lk(monitor);
        return cb.size();
    }
    void set_capacity(int capacity) {
        lock lk(monitor);
        cb.set_capacity(capacity);
    }
private:
    boost::condition buffer_not_empty;
    boost::mutex monitor;
    boost::circular_buffer<T> cb;
};

編輯這現在是一個模板類,它接受任何類型的對象(不僅僅是cv::Mat對象)。

是的。
如果您使用相同的鎖鎖定所有公共方法,它將是線程安全的。

你可以考慮使用讀寫鎖,如果你有很多並發讀者,它可能會有更好的性能。

如果你沒有很多讀者,它只會增加開銷,但可能值得檢查選項和測試。

我認為它看起來不錯,除了在send制作了一些毫無意義的 Mat 副本。 你不需要新的,你可以直接將send的參數推送到你的cb。

您的實現類似於此博主展示的實現 您應該閱讀該博客,看看您是否遺漏了實施中的任何內容。

如果您的Mat對象創建/復制成本很高,則應避免連續創建/復制/刪除它們。 相反,您應該有一個池(又名空閑列表)的 Mat 對象,這些對象在某種管道架構中不斷被回收 我在這個相關問題的回答中描述了這種類型的架構。

在那個答案中,我建議使用阻塞堆棧來實現池,但您也可以使用阻塞circular_buffer 我建議堆棧的原因是因為我認為它可能對緩存更友好,但我從未實際測量過它是否會有所作為。

很老的問題:) 這是一個帶有無鎖實現鏈接的dis gin

這是此鏈接的 BSD-2 Lib

//This implementation above is broken. You also need condition variable
//boost::condition buffer_not_full; and wait in send on available space in the circular buffer.
enter code here

void send (T imdata) {
   lock lk(monitor);
   while (cb.full())
      buffer_not_full.wait(lk);
   cb.push_back(imdata);
   buffer_not_empty.notify_one();
}

T receive() {
     lock lk(monitor);
     while (cb.empty())
        buffer_not_empty.wait(lk);
     T imdata = cb.front();
     cb.pop_front();
     buffer_not_full.notify_one();
     return imdata;
}

乍一看看起來不錯,只是您根本沒有使用buffer_not_full條件。 您可能想要添加類似於buffer_not_empty代碼的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM