C++11時代のWaitForMultipleObjects
スレッド周りのコードをwindowsAPIからC++11ライブラリの置き換えを随時やっていますが一番苦労したのがこれでした。
単に全部のスレッドが終わるのを待つだけなら全部のjoin呼べばいいだけなので簡単なのだが、タイムアウトがある場合が非常に厄介でした。
具体的には以下の様なコードがあった。
//windows API version unsigned int __stdcall ThreadFunctAPI( void* ) { ::Sleep( 10000 ); return 0; } //↑スレッド関数。使わなくてもvoid*引数とunsigned int戻り値が必要 int iThreadSize = 4; int time = 1000; std::vector< HANDLE > ahThread; for( int iThread = 0; iThread < iThreadSize; ++iThread ){ //スレッドの開始 ahThread.push_back( (HANDLE)_beginthreadex( NULL, 0, ThreadFunctAPI, NULL, 0, NULL ) ); } //待機 while( ::WaitForMultipleObjects( iThreadSize, ahThread.data(), TRUE, time ) == WAIT_TIMEOUT ){ //定期的に知らせる std::cout << '.'; } std::cout << std::endl; //スレッドを終わらせる for( int iThread = 0; iThread < iThreadSize; ++iThread ){ ::CloseHandle( ahThread[iThread] ); }
スレッドを複数まわしてその間は定期的に別の処理を走らせるような処理である。これの移植に非常に手間取った。joinにtimeoutはないのか?とか色々調べたがお手上げでした。結局、featureにwait_forという一定時間待つメソッドがあることに気がついたのでそれで頑張ることにした。
//C++11 version void ThreadFunct11() { std::this_thread::sleep_for(std::chrono::seconds(10)); } //↑スレッド関数。型は問わない。 int iThreadSize = 4; int time = 1000; std::vector< std::future< void > > aFutures; for( int iThread = 0; iThread < iThreadSize; ++iThread ){ //スレッドの開始 aFutures.push_back( std::move( std::async( std::launch::async, ThreadFunct11 ) ) ); } //待機 for( auto& f : aFutures ){ while( f.wait_for( std::chrono::milliseconds( time ) ) == std::future_status::timeout ){ //定期的に知らせる std::cout << '.'; } } std::cout << std::endl;
詳細なテストはまだだが多分うまく出来たと思われる。