{boost 1.54}
All asio operations are happening on the same io_service which has it's run() called from several std::threads (thus a thread-pool)
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
Is this safe? When main thread executes shrPtrProcess->stop();
thus deleting the slot from the Async's m_sig
and then comes out of the local scope, the last remaining reference to the shared_ptr to Process
will have died thus destroying it, but other thread firing m_sig
could have entered Process::slot(
) by then and about to execute line marked <1> above. Does signals2 guarantee that slots will not be deleted till they are executed completely?
If this is not safe then how do i achieve this behaviour of shrPtrProcess
destroying Process
ptr which in turn destroys Async
raw ptr in shrPtrAsync
once the local scope ends? If I don't do the hack in place marked <2> above I'll never be able to release resources if m_sig() does not fire anymore as signals2::connection::disconnect()
does not cause immediate deletion of slot.