C++ 线程安全、无数据竞争、无延迟的共享容器(循环缓冲区)
我面临以下情况(我必须承认我太笨了,无法相信自己能独自解决问题。)我有线程A,它偶尔会创建新的cv::Mat对象供线程B使用。我需要一个线程安全的容器C(在本例中是一个boost::circular_缓冲区),它将保存线程a生成的cv::Mat对象。然后,线程B需要不断迭代C中的所有项以生成动画。因此,我需要一个线程安全的C,它将不允许数据竞争,但也会导致线程B的动画没有(理想情况下)或非常小(如果不可能)的延迟->我不希望线程B在线程a更新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 &
#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“
,则不会出现错误?不,奇怪-它可能隐式包含在其他一些头中