使用类对象增强工作线程

时间:2013-04-02 13:36:27

标签: c++ multithreading concurrency

我是C ++并发的新手。我开始使用boost线程作为那些提供跨平台的解决方案。到目前为止,我看到的大多数示例都涉及将单独的函数传递给threads.Like this例如。我的情况我有一个类,它有几个类的实例,在我的例子中是OpenGL上下文和渲染相关的东西。 我已经知道将对象分配给线程是这样做的:

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

其中*这是指向调用它的实例的指针。 但是在这个类实例中复合的其他类呢?我应该为它们中的每一个做同样的事情,还是在我在宿主类上调用它们时它们会自动进行线程化? 我在this thread中概述了我的原始问题。所以,一旦我触发了线程,看起来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));

我尝试在线程init之后执行它,但然后它跳转到线程函数,使对象未初始化。 那么在具有所有内容的类上设置boost线程的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

简短回答:您需要将glMultiContext::getInstance().makeCurrent(_rc)调用new Engine()以及GPUThread构建函数中的GPUThread::operator()()调用移至makeCurrent()的开头。

更长的答案:似乎OpenGL上下文以某种方式绑定到特定线程,如here所示。您需要在要将上下文绑定到的线程中运行时调用makeCurrent() 您当前运行的线程是GPUThread的(完全隐式)参数。

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

我不明白设计OpenGL的{{1}}的理由。我最好的猜测是,他们必须在OpenGL上下文的实现中使用某种线程本地存储,或者其他东西。 “普通”2D Windows'设备上下文也有限制绑定到单个线程,这导致我猜测OpenGL可能有类似的限制。