There is a sample code which "works" in a multithreading environment:
void CSampleClass::Stop(void) {
if (m_pDB != nullptr) {
... Here is some code
m_pDB->Interrupt();
}
}
, where the m_pDB member is declared as boost::shared_ptr<CSampleDatabase> m_pDB;. m_pDB can be reset in another class method. That is why it is tested to not nullptr. As the code have multiple threads, can be a situation when m_pDB is reset, by another thread, in between if (...) and m_pDB->Interrupt();. The result is quite dramatic. To prevent such situation I use the following code modificationvoid CSampleClass::Stop(void) {
auto pDb = m_pDB; //lock
if (pDb != nullptr) {
... Here is some code
pDb->Interrupt();
}
}, i.e. if m_pDB.reset(); called, the object is never released until pDb is destroyed.
The questions are:
Is there a "standard" way to prevent the situation without involving lockers, mutexes, critical sections, etc.? Something like using
boost::weak_ptrto break circular references.Is it guaranteed that the compiler declares
pDBasboost::shared_ptr<CSampleDatabase>and notCSampleDatabase *? May be it is safer to writedecltype(m_pDB) pDb = m_pDB; //lock?
shared_ptris not an atomic operation.shared_ptrinstances referring to the same object and to modify thoseshared_ptrs concurrently, but it is not safe to concurrently modify/read a singleshared_ptrinstance.