用类对象提升线程工作器

Boost threads workers with class objects

本文关键字:线程 工作 对象      更新时间:2023-10-16

我是c++并发新手。我开始使用boost线程作为跨平台解决方案。到目前为止,我看到的大多数示例都处理将单独的函数传递到线程中的问题。比如这个。在我的例子中,我有一个类它有更多类的实例,在我的例子中是OpenGL context和渲染相关的东西。我已经了解到,将对象分配给线程是这样完成的:

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

其中*this是指向调用它的实例的指针。但是在这个类实例中是复合的其他类呢?我是否应该为它们中的每一个做同样的事情,或者它们是自动线程化的,一旦我在宿主类上调用它?我原来的问题概述在这个线程。一旦我启动线程它看起来OpenGL context仍然在主线程中。(参见底部的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上下文发出错误。我不能从缓冲区读取像素数据。我想这是因为我init _rc(渲染上下文)和设置当前上下文之前调用这个:

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

我尝试在线程初始化后这样做,但随后它直接跳过线程函数,留下未初始化的对象。那么,在类的所有内容上设置boost线程的正确方法是什么?

简短的回答:您需要将OpenGL调用glMultiContext::getInstance().makeCurrent(_rc)new Engine()调用从GPUThread构造函数移动到GPUThread::operator()()的开头。

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

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

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