【问题标题】:Boost threads workers with class objects使用类对象提升线程工作者
【发布时间】:2013-04-02 23:56:45
【问题描述】:

我是 C++ 并发的新手。我开始使用 boost 线程作为跨平台解决方案。到目前为止,我看到的大多数示例都涉及将单独的函数传递给线程。例如 this。就我而言我有一个类,它有几个类的实例,在我的例子中是 OpenGL 上下文和渲染相关的东西。 我了解到将对象分配给线程是通过这种方式完成的:

mythread=new boost::thread(boost::ref(*this));

其中 *this 是指向调用它的实例的指针。 但是在这个类实例中复合的其他类呢?我应该对它们中的每一个都做同样的事情,还是一旦我在宿主类上调用它们就会自动线程化? 我最初的问题在this 线程中进行了概述。所以,一旦我触发线程,它看起来就像 OpenGL 上下文仍保留在主线程中。(请参阅底部的 GPUThread 类)。

这是我的线程类:

  GPUThread::GPUThread(void)
  {
      _thread =NULL;
      _mustStop=false;
      _frame=0;


      _rc =glMultiContext::getInstance().createRenderingContext(GPU1);
      assert(_rc);

      glfwTerminate(); //terminate the initial window and context
      if(!glMultiContext::getInstance().makeCurrent(_rc)){

      printf("failed to make current!!!");
      }
         // init engine here (GLEW was already initiated)
      engine = new Engine(800,600,1);

   }
   void GPUThread::Start(){



      printf("threaded view setup ok");

       ///init thread here :
       _thread=new boost::thread(boost::ref(*this));
      _thread->join();

  }
 void GPUThread::Stop(){
   // Signal the thread to stop (thread-safe)
    _mustStopMutex.lock();
    _mustStop=true;
    _mustStopMutex.unlock();

    // Wait for the thread to finish.
    if (_thread!=NULL) _thread->join();

 }
// Thread function
 void GPUThread::operator () ()
{
       bool mustStop;

      do
     {
        // Display the next animation frame
        DisplayNextFrame();
        _mustStopMutex.lock();
        mustStop=_mustStop;
       _mustStopMutex.unlock();
    }   while (mustStop==false);

}


void GPUThread::DisplayNextFrame()
{

     engine->Render(); //renders frame
     if(_frame == 101){
         _mustStop=true;
     }
}

GPUThread::~GPUThread(void)
{
     delete _view;
     if(_rc != 0)
     {
         glMultiContext::getInstance().deleteRenderingContext(_rc);
         _rc = 0;
     }
    if(_thread!=NULL)delete _thread;
 }

当这个类运行 OpenGL 上下文时会发出错误。我无法从缓冲区中读取像素数据。我想这是因为我在调用它之前初始化了 _rc(渲染上下文)并设置了当前上下文:

 _thread=new boost::thread(boost::ref(*this));

我尝试在线程初始化之后执行此操作,但随后它直接跳到线程函数中,而对象未初始化。 那么在包含所有内容的类上设置 boost 线程的正确方法是什么?

【问题讨论】:

  • C++11 也为线程提供了跨平台的解决方案。
  • 我目前无法迁移到 C++ 11,因为我有一些旧库。
  • 我对 GPUThread::Start() 函数感到困惑。主线程大概是调用 GPUThread::Start(),然后阻塞调用_thread->join()。所以你只有一个线程在运行?
  • 等等...当您谈到 OpenGL“渲染上下文”时,Windows 上的某些东西可能会创建某种依赖于当前操作系统线程的上下文?
  • 这个网站:equalizergraphics.com/documentation/parallelOpenGLFAQ.html 有帮助吗?特别是第一个问题似乎暗示,当您在一个线程上创建 opengl 上下文时,您需要执行一些额外的 api 调用以将该上下文与任何其他线程相关联。大概他们(OpenGL 实现者)正在做某种线程本地存储黑客,这让您感到困惑?

标签: c++ multithreading concurrency


【解决方案1】:

简答:您需要将 OpenGL 调用 glMultiContext::getInstance().makeCurrent(_rc) 以及可能还有 new Engine() 调用从 GPUThread 构造函数移到 GPUThread::operator()() 的开头。

更长的答案:似乎 OpenGL 上下文以某种方式与特定线程相关联,如 here 所示。你需要调用makeCurrent()在你想绑定上下文的线程中运行。你当前运行的线程是makeCurrent()的一个(完全隐式的)参数。

你从你的主线程调用GPUThread构造函数,然后你从你的主线程调用GPUThread::Start()。您实际在子线程上运行的第一个位置是GPUThread::operator()() 函数的顶部。这就是必须调用glMultiContext::getInstance().makeCurrent(_rc) 的地方(在调用engine->Render() 之前)。

我不明白 OpenGL 的 makeCurrent() 的设计原理。我最好的猜测是,他们必须在 OpenGL 上下文的实现中使用某种线程本地存储,或者其他东西。 “正常”的 2D Windows 的设备上下文也有关于绑定到单个线程的限制,这让我猜测 OpenGL 可能有类似的限制。

【讨论】:

    猜你喜欢
    • 2016-02-23
    • 1970-01-01
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 2016-11-20
    相关资源
    最近更新 更多