CThreadPooler




スレッドの生成自体が結構、時間のかかる処理です。ゲームに限らず、一般的なアプリケーションにおいても、頻繁にスレッドを生成〜解体するのはあまり好ましくありません。

そこで、いくつかのスレッドを事前に用意して待機させておき、仕事をして欲しくなったときに、そのスレッドのなかで手すきになっているスレッドに対して、仕事を依頼する..というパターンが使われます。

yaneSDK3rdでも、スレッドプールというのがあって、事前にスレッドを生成してスレッドを待機させておくことが出来ます。

また、仕事の依頼は、汎用コールバック(smart_ptr<function_callback>)によって実現します。CThreadPoolerに対して、コールバックして欲しい関数を渡せば、そこに対してコールバックしてくれる、というものです。(この名前、ダサいんですが、CThreadPoolとかCThreadPoolManagerとかは、ATLとかで定義されてるのです(^^;)

list-1
void    CApp::MainThread() {
    CThreadPooler tp;
    tp.StartThread(3); // 3個のスレッドを走らせる
    smart_ptr<function_callback> fn;
    fn.Add(function_callback_v::Create(TestThread));
    //  TestThreadを走らせる

    for(int i=0;i<100;i++){
        tp.Invoke(fn);  //  100個の仕事をお願いする
    }

    while (tp.GetInvokeCount()) //  未処理の仕事の数を取得
        Sleep(10);
        //  ⇒上の2行は、単にtp.wait(); と書いても同じ意味

    //  --- すべての仕事が終了すると、ここから抜ける
}


仕事は、キュー構造になっていて、最初に積む(Invoke)したものから順番に実行されます。途中で、CThreadPoolerがスコープアウトした場合、CThreadPoolerのデストラクタが、自分の抱えているスレッドを停止させますので、その時点で残っている仕事は未処理になります。