c++ - 使用 Qt/C++ 从单独的线程发出对象时如何避免复制?

标签 c++ multithreading qt c++11 memory

我的目标:将子线程生成的对象传递给主程序线程,在主线程中读取它,并尽可能少地复制它。

什么有效

子线程拥有的对象,以这个字段作为中间存储:

private:
   cv::Mat rgb;

该字段的简单 getter 方法:

cv::Mat freenect2_pipe::take_rgb(){
    return this->rgb;
}

在将对象发射到主线程时使用以上两种方式:

    std::vector<cv::Mat> images;
    while (!stop_requested && !pause_requested
            && rgbd_camera.Capture(images)
            ) {
        rgb = images[0];
        emit rgb_frame(take_rgb());
    }

信号定义:

    void rgb_frame(const cv::Mat& image);

什么不起作用

-发射 (a) rgb_frame(images[0]),(b) rgb_frame(rgb),或 (c) rgb_frame(locally_created_copy_of_frame)。

它在哪里/如何失败?

尝试从生成的对象(在本例中为 OpenCV 矩阵)中读取时出现段错误。

*我如何实现目标?*s

附加信息

1) 上面的 images 数组是在第三个非 qt 线程中生成的,该线程由子线程启动。这发生在我无法修改的第三方代码中。

2) 无论我使用 QThreads 还是 C++11 线程(可能在我的平台上都在后台使用 pthread),段错误行为都是一致的。当直接使用 C++11 线程时,我创建了自己的中间共享缓冲区。因此 (void) 被发出,但主线程从队列上的共享缓冲区中弹出对象。然而,读取完全在同一个地方失败。

[编辑] 插槽定义:void tmp_display_rgb2(const cv::Mat& rgb);

最佳答案

有两种通用的解决方案。

#1 和#2 最小化复制,但只有#2 最小化内存分配。

解决方案 1:重新创建一个新的 shared_ptr 并在每次循环运行时在其中重新分配所需的数据项。使用线程之间共享的缓冲区来存储中间结果。

while (playback_allowed
    && rgbd_camera.Capture(*images)) {

    this->buffer->push_back(images); //push onto the buffer

    emit frame();
    images = hal::ImageArray::Create(); //re-initialize the shared pointer
}

解决方案 2(理论):在数据采集源处,创建一个交换缓冲区,在两个内存位置之间进行交换。在与上面的 Capture 方法等效的过程中,源一次应该只写入其中一个,返回指向该位置的指针,并在下一次迭代时交换位置。如果一切设置正确,生产者线程将在 Capture 敢于覆盖正在使用/处理的位置之前阻塞。

我能做的最好的就是使用解决方案 #1,因为我没有修改/覆盖/替换 Capture 方法的自由,该方法总是重新分配 的内容>图像。我采用了纯 C++11 线程解决方案,使用信号/插槽作为握手,并测试了两种缓冲区实现:一种使用锁,一种使用乐观重试。

理论上,也可以使用QThreads,缓冲区可能被Qt信号/槽机制提供的隐式队列所取代,这将需要发射整个shared_ptr。

关于c++ - 使用 Qt/C++ 从单独的线程发出对象时如何避免复制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31258946/

相关文章:

c++ - 定义 BOOST_TEST_DYN_LINK 会导致应用程序在 Visual Studio 中崩溃

c++ - 打印这个矩阵的 if 语句是什么

c++ - Eclipse PTP OpenMPI 并行运行/调试

c++ - OpenGL ES 2 如何渲染到纹理和提取数据用于 GPGPU 测试

java - Qt 占碑 : QAbstractListModel not displaying in QListView

c++ - 在 Linux 中,recv() 有效但 recvmsg() 无效

java - 一个线程只有一个实例

java - 如何通过 RequestFactory 高效使用 RestTemplate?

logging - 如何使用 Log4Net 登录每个线程的单独文件?

c++ - 你如何告诉 Qt 应用程序依赖于 Qt 库?