0

私は C++ の同時実行が初めてです。ブースト スレッドがクロス プラットフォーム ソリューションを提供するので、ブースト スレッドを使い始めまし。私の場合、OpenGLコンテキストとレンダリング関連のものでは、さらにいくつかのクラスのインスタンスがあります。スレッドへのオブジェクトの割り当ては次のように行われることを学びました。

mythread=new boost::thread(boost::ref(*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));

スレッドの初期化後に実行しようとしましたが、オブジェクトが初期化されずにスレッド関数にスキップします。では、すべてのコンテンツを含むクラスにブースト スレッドを設定する正しい方法は何でしょうか?

4

1 に答える 1

1

簡単な答え: OpenGL 呼び出しglMultiContext::getInstance().makeCurrent(_rc)と、おそらくコンストラクターnew Engine()からの呼び出しも の先頭に移動する必要があります。GPUThreadGPUThread::operator()()

より長い回答:ここに示されているように、OpenGL コンテキストは何らかの形で特定のスレッドに関連付けられているようです。makeCurrent() コンテキストを関連付けたいスレッドで実行中に呼び出す必要があります。 現在実行中のスレッドは、 への (完全に暗黙的な) 引数makeCurrent()です。

GPUThreadメインスレッドからコンストラクターを呼び出してGPUThread::Start()から、メインスレッドから呼び出しています。子スレッドで実際に実行している最初の場所は、GPUThread::operator()()関数の先頭です。glMultiContext::getInstance().makeCurrent(_rc)そのため、( への呼び出しの前に) を呼び出す必要がある場所engine->Render()です。

OpenGL の設計の根拠がわかりませんmakeCurrent()。私の推測では、彼らは OpenGL コンテキストの実装などである種のスレッド ローカル ストレージを使用しているに違いありません。「通常の」2D Windows のデバイス コンテキストには、単一のスレッドに結び付けられるという制限もあります。そのため、OpenGL にも同様の制限があるのではないかと推測しました。

于 2013-04-02T14:45:45.377 に答える