Singletonでのthread終了時にjoinで固まる
VisualStudio環境での話です(VS2012で確認)
gcc(4.9.2)環境では正常に動作します。
#include <thread> #include <atomic> #include <chrono> #include <iostream> class Hoge { public: static Hoge& get() { static Hoge hoge; return hoge; }; void run() { while( false == m_end ) { sleep(100); } } void stop() { m_end = true; } static void sleep(unsigned int ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } private: Hoge() : m_thread() , m_end(false) { m_thread = std::thread( &Hoge::run, this ); } virtual ~Hoge() { stop(); if ( m_thread.joinable() ) { m_thread.join(); } std::cout << "thread end" << std::endl; } Hoge(const Hoge& rhs); Hoge& operator=(const Hoge& rhs); std::thread m_thread; std::atomic<bool> m_end; }; int main() { Hoge::get(); Hoge::sleep(100); return 0; }
上記のコードを実行すると終了時に固まります。
何が起こっているかというと多分以下の通り
・mainが終了
・Hogeのデストラクタで動かしている子供スレッドの終了指示
・joinで子供スレッドが終わるのを待つ
・run関数自体は終わるが_Cnd_do_Broadcast_at_thread_exitでメインスレッドの終了待ちをしている?
・結果joinとメインスレッド終了待ちでデッドロック。
いまのところ、とりあえずjoinをdetachに変えてしのいでます。
if ( m_thread.joinable() ) { #if 0 m_thread.join(); #else m_thread.detach(); #endif }
ちなみに_Cnd_do_Broadcast_at_thread_exitを通るのを確認するために
ランタイムライブラリのオプションを/MTdにしてます。