什么时候通过优化去除变量?

时间:2013-07-12 16:08:21

标签: c++ multithreading optimization volatile

我正在使用线程,我对如何允许编译器优化以下代码有疑问:

void MyClass::f(){
    Parent* p = this->m_parent;
    this->m_done = true;
    p->function();
}

使用p(在堆栈或寄存器中)来调用函数而不是this->m_parent非常重要。因为只要m_done成为true,就可以从另一个线程中删除this,如果它碰巧运行了它的清理过程(由于这个原因我实际上已经崩溃了),在这种情况下{ {1}}可能包含垃圾,但线程堆栈/寄存器将完好无损。

我在GCC / Linux上的初步测试显示我没有竞争条件,但我想知道其他编译器是否也会出现这种情况?

这是 gulp m_parent的情况吗?我看过What kinds of optimizations does 'volatile' prevent in C++?Is 'volatile' needed in this multi-threaded C++ code?,但我不觉得其中任何一个都适用于我的问题。

由于我不确定允许编译器在这里做什么,我感到不安。我看到以下情况:

  • 否/有益优化,volatile中的指针存储在堆栈/寄存器中,此值稍后用于调用this->m_parent这是想要的行为。
  • 编译器删除function(),但p已经在寄存器中可用,并且编译器使用它来调用this->m_parent会起作用但在编译器之间不可靠。这很糟糕,因为它可能会暴露移动到不同平台/编译器版本的错误。
  • 编译器删除function()并在调用p之前读取this->m_parent,这会产生一种我无法拥有的竞争条件。

请问有人可以了解允许编译器在这里做什么吗?

修改

我忘了提到function()this->m_done而我正在使用C ++ 11。

3 个答案:

答案 0 :(得分:2)

如果m_donestd::atomic<bool>,则此代码将完全按照C ++ 11编写。 m_parent的读取写入m_done之前进行了排序,这将与测序的另一个线程中的m_done的假设读取同步 - 在假设写入m_parent之前。总而言之,这意味着标准保证此线程读取m_parent 发生在其他线程的写入之前。

答案 1 :(得分:1)

您可能会遇到重新排序问题。检查内存屏障以解决此问题。放置它,以便p的加载和m_done的设置完全按照这个顺序完成(将它放在两个指令之间),你应该没问题。

实现在C ++ 11和boost中可用。

答案 2 :(得分:-1)

嗯,当你在其中一个成员函数中时,其他一些线程可能会从你下面删除该对象?未定义的行为。简单明了。