Рассмотрим следующий код:
#include <atomic>
extern std::atomic<int> i;
void f(void)
{
while (!i.load(std::memory_order_relaxed))
;
}
Я ищу цитату из стандарта C ++ 11, в которой говорится, что компилятору не разрешено преобразовывать цикл в
if (!i.load(std::memory_order_relaxed)) {
while (1)
;
}
Я видел некоторое обсуждение Вот но ничего неопровержимого.
редактироватьПредыдущая версия этого поста называлась внешней функцией внутри цикла.
Редактировать 2: Для мотивации: в книге «Эффективная Java» говорится, что виртуальная машина HotSpot выполняет следующее преобразование:
while (!done)
i++;
в
if (!done)
while (true)
i++;
хотя это совершенно определенное поведение для другого потока, чтобы изменить сделанный переменная одновременно.
Забудьте о расслабленном, нет гарантии, что атомный магазин Когда-либо стать видимым для атомной нагрузки в другом потоке. Лучшее, что вы получаете, это нормативное поощрение в [Atomics.order] / 12 (и аналогичная формулировка в [Intro.progress] / 18):
Реализации должны сделать атомные хранилища видимыми для атомных нагрузок
в разумные сроки.
…что не является обязательным требованием.
(C11 имеет идентичную формулировку в §7.11.3 / 16)
Так как подъем нагрузки приводит к поведению, неотличимому от не поднятой нагрузки, когда хранилище никогда не становится видимым, и, поскольку последнее является соответствующим, по правилу «как будто» реализация позволяет поднимать нагрузку независимо от используемого порядка памяти.
Других решений пока нет …