C++ 线程安全、无数据竞争、无延迟的共享容器(循环缓冲区)

C++ 线程安全、无数据竞争、无延迟的共享容器(循环缓冲区),c++,multithreading,c++11,thread-safety,circular-buffer,C++,Multithreading,C++11,Thread Safety,Circular Buffer,我面临以下情况(我必须承认我太笨了,无法相信自己能独自解决问题。)我有线程A,它偶尔会创建新的cv::Mat对象供线程B使用。我需要一个线程安全的容器C(在本例中是一个boost::circular_缓冲区),它将保存线程a生成的cv::Mat对象。然后,线程B需要不断迭代C中的所有项以生成动画。因此,我需要一个线程安全的C,它将不允许数据竞争,但也会导致线程B的动画没有(理想情况下)或非常小(如果不可能)的延迟->我不希望线程B在线程a更新C时冻结。我能想到的最好办法是: #include &

我面临以下情况(我必须承认我太笨了,无法相信自己能独自解决问题。)我有线程A,它偶尔会创建新的cv::Mat对象供线程B使用。我需要一个线程安全的容器C(在本例中是一个boost::circular_缓冲区),它将保存线程a生成的cv::Mat对象。然后,线程B需要不断迭代C中的所有项以生成动画。因此,我需要一个线程安全的C,它将不允许数据竞争,但也会导致线程B的动画没有(理想情况下)或非常小(如果不可能)的延迟->我不希望线程B在线程a更新C时冻结。我能想到的最好办法是:

#include <boost/circular_buffer.hpp>
#include <opencv2/core.hpp>
#include <boost/core/noncopyable.hpp>
#include <memory>
#include <type_traits>
#include <algorithm>

using im_buf = boost::circular_buffer<cv::Mat>;
class ImageBuffer : private boost::noncopyable { 
private:
  im_buf buffer;
  std::mutex mtx;
  std::unique_lock<std::mutex> lock;
public:
  // operator<< accepting cv::Mat, cv::Mat& and cv::Mat&&
  template <class T,
    class = typename std::enable_if
    <std::is_same<cv::Mat, typename std::decay<T>::type>
     ::value>::type>
   void operator<<(T&& mat) {
      lock.lock();
      buffer.push_back(std::forward<T>(mat));
      lock.unlock();
    }
    template <typename Func> // excpect callable objects only
    inline void iterate(Func func) {
      lock.lock();
      std::for_each(buffer.begin(),buffer.end(),func);
      lock.unlock();
    }
    inline ImageBuffer():
      buffer {settings::max_images_in_loop},
      mtx {},
      lock {mtx} {}
    ~ImageBuffer()=default;
    ImageBuffer(const ImageBuffer&&)=delete; 
    ImageBuffer& operator=(const ImageBuffer&&)=delete;  
};
#包括
#包括
#包括
#包括
#包括
#包括
使用im_buf=boost::circular_buffer;
类ImageBuffer:private boost::不可复制{
私人:
缓冲区;
std::互斥mtx;
std::唯一的_锁;
公众:

//操作符如果您的问题是动画,那么您担心的是错误的事情。互斥锁适合您的目的-不要担心延迟

理想情况下,您需要以60帧/秒的速度制作画面。根据您的应用程序,您可能只需要20帧/秒。在数字电影出现之前,电影院仅播放24帧/秒

60fps意味着您有16毫秒的时间来渲染帧。在1GHz处理器上,有1600万个时钟周期。为了避免由于其他进程而导致的口吃,您需要使用少于一半的时间,例如400-800万个周期,因此50%到75%的处理器时间是空闲的,而渲染帧只需要4-8毫秒的处理器时间

等待其他线程、互斥体或其他资源只会在导致您错过下一帧的截止日期时影响动画


如果由于互斥,线程每隔几帧就要等待数万个时钟周期,这不会影响渲染,因为在下一帧显示在屏幕上之前,您还有足够的时间。

如果您的问题是动画,您担心的是错误的事情。互斥适合您的目的-不要担心拖延

理想情况下,您需要以60帧/秒的速度制作画面。根据您的应用程序,您可能只需要20帧/秒。在数字电影出现之前,电影院仅播放24帧/秒

60fps意味着您有16毫秒的时间来渲染帧。在1GHz处理器上,有1600万个时钟周期。为了避免由于其他进程而导致的口吃,您需要使用少于一半的时间,例如400-800万个周期,因此50%到75%的处理器时间是空闲的,而渲染帧只需要4-8毫秒的处理器时间

等待其他线程、互斥体或其他资源只会在导致您错过下一帧的截止日期时影响动画


如果你的线程每隔几帧就要等待一次,由于互斥锁的原因需要等待数万个时钟周期,这不会影响你的渲染,因为在下一帧显示在屏幕上之前,你还有很多时间。

你的
lock
成员变量实际上应该是每个函数中的局部变量。如果你这样做了您也不需要显式解锁,当作用域离开时会发生这种情况。请查看和的使用示例。您可以检查以查看互斥锁是否已锁定。如果互斥锁已锁定,请继续其过程。如果互斥锁未锁定,请迭代所有项以生成动画。
std::互斥mtx;
不带
#包括"
?不,奇怪-它可能隐式包含在其他一些标题中。您的
lock
成员变量实际上应该是每个函数中的局部变量。如果这样做,您也不需要显式解锁,它会在离开作用域时发生。请查看和的用法示例。您可以检查以查看互斥锁是否为locked.如果互斥锁被锁定,B继续其过程。如果互斥锁未被锁定,B迭代所有项以生成动画。如果
std::mutex mtx;
没有
#include“
,则不会出现错误?不,奇怪-它可能隐式包含在其他一些头中