线程安全、无数据争用、无延迟的共享容器 (circular_buffer)
thread-safe, data-race free, lag-free shared container (circular_buffer)
我面临以下情况(我不得不承认我太菜鸟了,不能相信自己独自解决..(:我有线程 A,它偶尔会创建新的 cv::Mat 对象供线程 B 使用。我需要一个线程安全的容器 C(在这种情况下为 boost::circular_buffer(,它将容纳线程 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;
};
(请注意,即使这不是一个不变的,线程 B 也不应该改变 C 或其任何内容(我很想在这里使用const_iterator,但 boost::circular_buffer 不提供......
然而,使用此代码,每次线程 A 添加新元素时,线程 B 都会将整个动画冻结一段时间。答:难道没有更好的方法吗?b. 实现真的是线程安全的吗?
如果你的问题是动画,你担心的是错误的事情。互斥体适合您的目的 - 不必担心停滞。
理想情况下,您需要以 60fps 的速度生成帧。根据您的应用,您可能会以低至 20fps 的速度逃脱。在数字电影出现之前,电影院只显示24fps。
60fps 意味着您有 16 毫秒的时间来渲染帧。在 1GHz 处理器上,时钟周期为 1600 万个。为了避免由于其他进程而导致卡顿,您需要使用不到一半的时间,例如 4-800 万个周期,因此 50% 到 75% 的处理器时间处于空闲状态,并且您只使用 4-8 毫秒的处理器时间来渲染帧。
等待其他线程、互斥锁或其他资源只会在导致您错过下一帧的截止时间时影响您的动画。
如果您的线程必须每隔几帧等待一次,由于互斥锁而等待几万个时钟周期,这不会影响您的渲染,因为在下一帧显示在屏幕上之前您仍然有足够的时间。
- 如何"buffer" UNIX 信号
- 什么是 Direct3D 12.0 上的"Map Default Buffer"?
- VC++ wcscpy_s随机断言"Buffer is too small"
- 将uint8_t*buffer和size_tbufferlen从C++传递到C中的API函数的最佳方式是什么
- boost::asio::buffer 如何遍历字节
- 大约"circular reference",我用了weak_ptr但仍然发生内存泄漏
- 在 boost::<double>asio::buffer 中使用像 std::vector<std::complex> 这样的参数
- Cppcheck 静态代码分析器实际上可以检测到不太常见的警告(如 "Relative Path Traversal (CWE-23)" 或"Buffer Under-read(CWE-127)")吗
- tf2_ros::Buffer::canTransform() 为现有转换返回 False
- OpenCL/C++ - 返回一个 cl::Buffer 对象
- 如何在方法参数中使用boost :: asio :: buffer
- 尝试运行 NVIDIA FleX 时"buffer overflow detected"
- C++: buffer the cin istream
- 如何将 std::array 转换为 boost::asio::buffer
- 如何从节点本机插件正确创建Buffer对象
- Buffer.BlockCopy Array 2d c++ to C# 共享内存
- opencv imencode() buffer exception
- boost::asio::buffer与矢量结构
- boost::circular buffer等效于文件
- 执行boost::circular buffer确认自动弹出操作