多くの場合、アクティブ オブジェクトのように動作する (スレッドを持つ) クラスがあります。アクセス違反を避けるために、私は常にデストラクタに参加するのを待たなければなりません。これは通常問題ではありません。
ただし、何らかのバグ (デッドロック、ライブロックなど) があるリリース ビルドを想像してみてください。これにより、join()
時間どおりに返されないか、まったく返されません。これにより、再度使用されないオブジェクトを待機している間、アプリケーション全体が機能しなくなります。これが顧客で発生すると、問題になります。
私はむしろ問題によって通知され、参加をスキップしたいと思います。そして、スレッドとそのリソースをリークします。
結合のスキップは、このような方法で実現できます。
class MyActiveObject
{
public:
MyActiveObject();
~MyActiveObject(){}
private
struct Implementation;
std::shared_ptr<Implementation> pImpl_;
};
struct MyActiveObject::Implementation : std::enable_shared_from_this<Implementation >
{
Implementation() : thread_([=]{Run();})
{
}
~Implementation()
{
#ifdef _DEBUG
thread_.join();
#else
if(!thread_.timed_join(SOME_TIMEOUT))
ALERT_SOME_HOW();
#endif
}
void Dispose()
{
isRunning_ = false;
}
void Run()
{
#ifndef _DEBUG
auto pKeepAlive = shared_from_this(); // Won't be destroyed until thread finishes
#endif
isRunning_ = true;
while(isRunning_)
{
/* ... */
}
}
boost::thread thread_;
tbb::atomic<bool> isRunning_;
};
MyActiveObject::MyActiveObject() : pImpl_(new Implementation()){}
MyActiveObject::~MyActiveObject() { pImpl_->Dispose(); }
これは良い考えですか?または、より良い戦略はありますか?