{ブースト 1.54}
すべての asio 操作は、複数の std::threads (したがってスレッドプール) から呼び出された run() を持つ同じ io_service で発生しています。
struct Async : std::enable_shared_from_this<Async>
{
boost::signals2::signal<void()> m_sig;
void read()
{
auto self = shared_from_this();
boost::asio::async_read_until(
/*socket*/,
/*bufferToCollectData*/,
/*delimiter*/,
[self]{self->onRead(..);}
);
}
void onRead(..)
{
m_sig();
}
};
struct Process : std::enable_shared_from_this<Process>
{
std::shared_ptr<Async> m_shrPtrAsync;
boost::signals2::connection m_connection;
void start()
{
m_shrPtrAsync = std::make_shared<Async>();
//m_shrPtrAsync->startUpThings();
auto self = shared_from_this();
m_connection = m_shrPtrAsync->m_sig.connect(
[self]{self->slot();}
);
}
void stop()
{
//this will not delete the slot and have to wait indefinitely until some operation happens on m_sig.
//------------------------------- <2>
m_connection.disconnect();
//this should force the original slot deletion.
m_connection = m_shrPtrAsync->m_sig.connect([this]{dummy();});
m_connection.disconnect();
}
void dummy() {}
void slot()
{
auto self = shared_from_this(); //-------------------- <1>
//to not block the calling thread (Async's m_sig())
m_strand.post(
[self]{self->slotPrivateImpl();}
);
}
void slotPrivateImpl() { /*Processing*/ }
};
//This is from the main thread outside the thread-pool
{//local scope begins
auto shrPtrProcess = std::make_shared<Process>();
shrPtrProcess->start();
//after sometime
shrPtrProcess->stop();
}//local scope ends. I want shrPtrProcess to delete the contained pointer here
//which should in turn delete the Async's pointer in shrPtrProcess->m_shrPtrAsync
これは安全ですか?メイン スレッドが実行shrPtrProcess->stop();
され、Async からスロットが削除m_sig
され、ローカル スコープから出ると、最後に残っていた shared_ptr への参照が終了Process
して破棄されますが、それまでに他のスレッドが起動して )m_sig
に入りProcess::slot(
、行を実行しようとしている可能性があります。上記の<1>とマークされています。シグナル2は、スロットが完全に実行されるまで削除されないことを保証しますか?
これが安全でない場合、ローカル スコープが終了すると、ptr を破棄shrPtrProcess
するというこの動作を実現するにはどうすればよいですか? 上記の <2> とマークされた場所でハックを行わないと、スロットがすぐに削除されないため、m_sig() が起動しなくなった場合にリソースを解放できなくなります。Process
Async
shrPtrAsync
signals2::connection::disconnect()