I'm working with threads and I have question about how the compilers are allowed to optimize the following code:
void MyClass::f(){
Parent* p = this->m_parent;
this->m_done = true;
p->function();
}
It is very important that p
(on the stack or in a register) is used to call the function instead of this->m_parent
. Since as soon as m_done
becomes true
then this
may be deleted from another thread if it happens to run its cleanup pass (I have had actual crashes due to this), in which case m_parent
could contain garbage, but the thread stack/registers would be intact.
My initial testing on GCC/Linux shows that I don't have a race condition but I would like to know if this will be the case on other compilers as well?
Is this a case for gulp volatile
? I've looked at What kinds of optimizations does 'volatile' prevent in C++? and Is 'volatile' needed in this multi-threaded C++ code? but I didn't feel like either of them applied to my problem.
I feel uneasy relying on this as I'm unsure what the compiler is allowed to do here. I see the following cases:
- No/Beneficial optimization, the pointer in
this->m_parent
is stored on the stack/register and this value is later used to callfunction()
this is wanted behavior. - Compiler removes
p
butthis->m_parent
is by chance available in a register already and the compiler uses this for the call tofunction()
would work but be unreliable between compilers. This is bad as it could expose bugs moving to a different platform/compiler version. - Compiler removes
p
and readsthis->m_parent
before the call tofunction()
, this creates a race condition which I can't have.
Could some one please shed some light on what the compiler is allowed to do here?
Edit
I forgot to mention that this->m_done
is a std::atomic<bool>
and I'm using C++11.