2

ブーストスレッドを使用してopengl関数を実行しています.メインスレッドは、標準入出力を介して外部プログラムと通信することを目的としています. その理由は、opengl がメイン ループに入ると、そこから離れることはありませんが、レンダリングをブロックせずに入力を読み込む方法が必要だからです。プログラムが入力を受け取ると、メイン プログラムは静的メンバーを介して opengl スレッドと通信します (単に値を変更するだけです)。

class ARGraphicController
{
    public:
        ARGraphicController(int sw, int sh);
        ~ARGraphicController();
        //...
        void start(int argc, char *argv[]);
        static void changeGen();
        static bool genMove;
    private:
        //..
};


bool ARGraphicController::genMove;
void ARGraphicController::start(int argc, char *argv[])
{
    //opengl initialization
    //./
    glutMainLoop();
}

これが私のメインです

void main()
{
    graphic_handler = new boost::thread(boost::bind(&ARGraphicController::start, &graphic_controller, argc, argv));

    string command_line;

    while(1)
    {
        getline(cin, command_line);
        //process input command
        //...
        //...

        if(command == "genmov"){
            //change static variable to true
            graphic_controller.changeGen();
            while(1)
            {
            //until the thread change the static variable back to false
                if(!graphic_controller.genMove)
                {
                    //...
                    break;
                }       
            }
        }

    }
    delete graphic_handler;
}

私が理解していないのは、これを行うと、changeGen() が静的変数の値を変更しないことです。

void ARGraphicController::changeGen()
{
    genMove = true;
}

しかし、std::cout を追加すると、値が変更されます。

void ARGraphicController::changeGen()
{
    genMove = true;
    std::cout<<"value is changed :)"<<std::endl;
}

静的メンバー変数 (本質的にグローバルな変数) がスレッドセーフではないという事実と関係があると思いますか? もしそうなら、どうすればこの問題を解決できますか? または、メインとスレッド間の通信用にアプリケーションを設計するより良い方法はありますか?

ありがとう

4

1 に答える 1

1

メモリ順序付けのすばらしい世界へようこそ。

ここでの問題は、現在のセットアップでは、書き込まれた値がいつ他のスレッドから見えるようになるかという保証がないことです。コンパイラ、CPU、キャッシュ、またはメモリ コントローラー (および場合によっては他のコントローラー) のいずれかが、2 番目のスレッドで変更が表示されないようにする最適化をここに挿入できます。それとは別に、データ競合もあります。bool への非同期アクセスは、ほとんどの最新のアーキテクチャで機能しますが、他のアーキテクチャではひどく壊れる可能性があります。ISO-C++11 では、このようなデータ競合はすぐに未定義の動作を引き起こします。

解決策は、スレッド ライブラリを利用することです。ここでの最も簡単な修正は、単純atomic<bool>に静的変数に an を使用することです。これにより、順序付けとアクセスの問題の両方が処理されます。または、メッセージ パッシング プリミティブの 1 つを検討してください。

  • 1 回限りのイベントを通知するために使用boost::futureします。
  • スレッドが待機できる繰り返し条件を通知するために使用boost::condition_variableします (ここではプロデューサー/コンシューマーが顕著な例です)。
  • 多数の均一なメッセージを送信する場合は、boost.lockfree の lockfree キューを使用して、スレッド間のデータ ストリームを確立します
于 2013-06-24T08:00:04.337 に答える