Переупорядочение компилятора вокруг взаимоисключающих границ?

Предположим, что у меня есть свои собственные неподставляемые функции LockMutex и UnlockMutex, которые используют некоторое надлежащее взаимное исключение - такое как повышение - внутри. Как компилятор будет знать для не переупорядочения других операций относительно вызовов к LockMutex и UnlockMutex? Это не может возможно знать, как я реализую эти функции в некоторой другой единице компиляции.

void SomeClass::store(int i)
{
  LockMutex(_m);
  _field = i;  // could the compiler move this around?
  UnlockMutex(_m);
}

PS: Каждый, как предполагается, использует экземпляры классов для фиксаторов для гарантии разблокирования. Я пропустил это для упрощения примера.

7
задан shojtsy 22 April 2010 в 22:38
поделиться

6 ответов

Возможно, он не знает, как я буду реализовывать эти функции в каком-нибудь другом модуле компиляции.

Это ключ - поскольку компилятор не может знать (в общем) о реализации вызовов функций, он не может переместить хранилище в _field вне этих вызовов функций.

Обычно, поскольку _field доступен за пределами SomeClass :: store () (он не локальный), компилятор не может знать, было ли оно изменено внешним функция, поэтому она должна выполнять сохранение в _field между точками последовательности вызовов функций.

Базовая аппаратная платформа может нуждаться в некотором внимании в виде барьеров памяти или очистки кеша, чтобы иметь дело с кэшированием или неупорядоченными операциями, которые происходят в оборудовании. Реализация API мьютексов на платформе при необходимости решит эти проблемы.

2
ответ дан 7 December 2019 в 09:58
поделиться

Если бы компилятор делал это, это был бы плохой компилятор. ; -)

0
ответ дан 7 December 2019 в 09:58
поделиться

В общем, компилятор не будет перемещать код, если он не знает с уверенностью, что это не повлияет на поведение во время выполнения.

2
ответ дан 7 December 2019 в 09:58
поделиться

Вы правы, этот код правильный и безопасный. Я все же придумал "шутку о коде".

pthread_mutex_lock( &mx ) + foo() + pthread_mutex_unlock( &mx );
1
ответ дан 7 December 2019 в 09:58
поделиться

Как написано, если функции не встроены, компилятор не будет перемещать присвоение переменной, поскольку вызов может не иметь отношения к переменной _field, но он должен сохранять строгий порядок вызовов. Если, однако, компилятор решит встроить вызовы, я думаю, он будет рассматривать их как блоки независимого кода, то есть он будет переупорядочивать инструкции только в том же блоке кода (сама встроенная функция), но не со следующими или предшествующими код (присвоение переменной _field).

1
ответ дан 7 December 2019 в 09:58
поделиться

Если компилятор не может гарантировать, что вызовы функций не будут иметь побочных эффектов, которые изменят переменные между вызовами, он не может переместить код. Если переменная является локальной переменной, и вы никогда не использовали ссылку или не создавали указатель на нее, компилятор может предположить, что ее перемещение безопасно; Я не знаю.

0
ответ дан 7 December 2019 в 09:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: