我正在使用线程,我对如何允许编译器优化以下代码有疑问:
void MyClass::f(){
Parent* p = this->m_parent;
this->m_done = true;
p->function();
}
非常重要的是p
(在堆栈上或在寄存器中)用于调用函数而不是this->m_parent
. 因为如果它碰巧运行它的清理过程(我已经因此而发生实际崩溃),那么它可能会从另一个线程中删除,在这种情况下m_done
可能true
包含垃圾,但线程堆栈/寄存器将是完整的。this
m_parent
我在 GCC/Linux 上的初始测试表明我没有竞争条件,但我想知道其他编译器是否也会出现这种情况?
这是gulp volatile
的情况吗?我已经查看了 C++ 中的“易失性”阻止了哪些优化?在这个多线程 C++ 代码中是否需要“易失性”?但我不觉得他们中的任何一个都适用于我的问题。
我对此感到不安,因为我不确定编译器可以在这里做什么。我看到以下情况:
- 没有/有益的优化,指针
this->m_parent
存储在堆栈/寄存器中,这个值稍后用于调用function()
这是想要的行为。 - 编译器删除
p
但this->m_parent
偶然在寄存器中可用,编译器使用它来调用function()
将起作用,但在编译器之间不可靠。这很糟糕,因为它可能会暴露移动到不同平台/编译器版本的错误。 - 编译器在调用 之前删除
p
并读取,这会产生我不能拥有的竞争条件。this->m_parent
function()
有人可以阐明编译器在这里允许做什么吗?
编辑
我忘了提到那this->m_done
是一个std::atomic<bool>
,我正在使用 C++11。