スレッドはそれ自体を切り離し、そのリソースを解放する可能性があります。デストラクタがスレッドが結合可能である、つまりまだ実行中であることを確認した場合は、スレッドを結合させます。スレッドが終わりに達した場合は、セルフデタッチします。考えられる競合状態:is_joinable()はデストラクタでtrueを返します-スレッドはそれ自体をデタッチします-デストラクタは結合し、惨めに失敗します。したがって、スレッドの停止を保護するミューテックスを使用します。
struct ThreadContainer
{
std::mutex threadEndMutex;
std::thread theThread;
ThreadContainer()
: theThread([=]()
{
/* do stuff */
// if the mutex is locked, the destructor is just
// about to join, so we let him.
if (threadEndMutex.try_lock())
theThread.detach();
})
{}
~ThreadContainer()
{
// if the mutex is locked, the thread is just about
// to detach itself, so no need to join.
// if we got the mutex but the thread is not joinable,
// it has detached itself already.
if (threadEndMutex.try_lock() && theThread.is_joinable())
theThread.join();
}
};
PS:スレッドがそれ自体を切り離した場合、ミューテックスのロックが解除されず、try_lockが失敗するため、is_joinableを呼び出す必要がない場合もあります。
PPS:ミューテックスの代わりに、std :: atomic_flag:を使用できます。
struct ThreadContainer
{
std::atmoic_flag threadEnded;
std::thread theThread;
ThreadContainer()
: threadEnded(ATOMIC_FLAG_INIT)
, theThread([=]()
{
/* do stuff */
if (!threadEnded.test_and_set())
theThread.detach();
})
{}
~ThreadContainer()
{
if (!threadEnded.test_and_set())
theThread.join();
}
};