Я работаю с потоками и у меня есть вопрос о том, как компиляторы могут оптимизировать следующий код:Когда переменные удаляются оптимизацией?
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 показывает, что у меня нет состояния гонки, но я хотел бы знать, будет ли это так и в других компиляторах?
Это случай для gulpvolatile
? Я посмотрел на What kinds of optimizations does 'volatile' prevent in C++? и Is 'volatile' needed in this multi-threaded C++ code?, но я не чувствовал, что любой из них применил мою проблему.
Я чувствую себя неловко, полагаясь на это, поскольку я не уверен, что здесь разрешен компилятор. Я вижу следующие случаи:
- оптимизация No/Благодатная, указатель в
this->m_parent
хранятся в стеке/регистре, и это значение в дальнейшем используются для вызоваfunction()
это разыскивается поведение. - Компилятор удаляет
p
, ноthis->m_parent
случайно представлен в регистре, и компилятор использует это для вызоваfunction()
, но он будет ненадежным между компиляторами. Это плохо, так как это может привести к перебору ошибок в другой версии платформы/компилятора. - Компилятор удаляет
p
и читаетthis->m_parent
перед вызовомfunction()
, это создает состояние гонки, которое у меня не может быть.
Может ли кто-нибудь пролить свет на то, что здесь разрешен компилятор?
Редактировать
Я забыл упомянуть, что this->m_done
является std::atomic<bool>
, и я использую C++ 11.
Ключевое слово 'register' будет делать то, что я хочу, если компилятор будет уважать его ... –
это не проблема волатильности/регистрации. Это проблема переупорядочения. Компилятору разрешено устанавливать m_done в true до того, как он загрузит m_parent. –
Также «volatile» заставит считывать память с шины, что на самом деле не так (хотя это, вероятно, может быть использовано для решения моей проблемы). Я просто хочу сказать компилятору «Довольно, пожалуйста, сохраните это значение в регистре», потому что он скоро исчезнет, и мне понадобится копия « –