スレッド

簡単だけどそれなりのスレッドクラスを作りたいがどうしたものか。

調べてるみると
(1) コンストラクタで _beginthredex を実行するタイプ
(2) 別関数で _beginthredex を実行するタイプ
とやってるものを見かける。

symbian とか弄っていた経緯からコンストラクタでこういった処理はしたくないんだよね。
となると (2) しかないわけなんだけど、これはイイ!という実装が見当たらない。
例えば start() という関数で _beginthredex を実行する場合、pubilic メンバ関数だから
誤って何度もコールされる可能性は絶対にある。
注意書きで対処とか格好悪いよね(汗
// @warning start() は一度しか呼んではダメ!

とりあえず CloseHandle() でハンドル開放していたら OK なノリだと

void Thread::start(unsigned (__stdcall* func)(void*)){
  if(!thread_handle){
    thread_handle = (HANDLE)_beginthreadex(NULL, 0, func, this, CREATE_SUSPENDED, &thread_index);
  }
  ・・・レジューム
}

void Thread::close(){
  if(thread_handle){
    WaitForSingleObject(thread_handle, INFINITE);
    CloseHandle(thread_handle);
  }
}

// @warning close() 呼び出しを行っていない start() の動作は不定です!

とりあえずおかしな動作にはならないという最低限の保障はできるが、
利用者からすると start() をコールしているのにスレッドが走らないというのはやはり違和感のある実装。

void Thread::start(unsigned (__stdcall* func)(void*)){
  close();
  ・・・スレッド生成
}

何か走っている場合は終わるまで待ってから生成。
一応リエントランスといえばそうだけど、、、

// @warning 速やかに起動しない場合があります!

となると強制終了しかなくなるが・・・スレッド処理次第で嫌な予感がするね。
ついでにスレッドリソースの構築/破棄は明示的に指定されない限りは一度に留めておいて再利用したいところ。

厄介だねぇ・・・コメントに一筆しておくか(ゴホゴホ