Я пытаюсь реализовать простую функцию занятого цикла.
Это должно продолжать опрашивать переменную std :: atomic максимальное количество раз (spinCount) и возвращать true, если статус действительно изменился (на что-либо, кроме NOT_AVAILABLE) в данных попытках, или false в противном случае:
// noinline is just to be able to inspect the resulting ASM a bit easier - in final code, this function SHOULD be inlined!
__declspec(noinline) static bool trySpinWait(std::atomic<Status>* statusPtr, const int spinCount)
{
int iSpinCount = 0;
while (++iSpinCount < spinCount && statusPtr->load() == Status::NOT_AVAILABLE);
return iSpinCount == spinCount;
}
Однако, похоже, что MSVC просто оптимизирует цикл в режиме Release для Win64.Я очень плохо отношусь к Assembly, но мне не кажется, что она вообще пытается прочитать значение statusPtr:
int iSpinCount = 0;
000000013F7E2040 xor eax,eax
while (++iSpinCount < spinCount && statusPtr->load() == Status::NOT_AVAILABLE);
000000013F7E2042 inc eax
000000013F7E2044 cmp eax,edx
000000013F7E2046 jge trySpinWait+12h (013F7E2052h)
000000013F7E2048 mov r8d,dword ptr [rcx]
000000013F7E204B test r8d,r8d
000000013F7E204E je trySpinWait+2h (013F7E2042h)
return iSpinCount == spinCount;
000000013F7E2050 cmp eax,edx
000000013F7E2052 sete al
У меня сложилось впечатление, что std :: atomic с std ::memory_order_sequential_cst создает барьер компилятора, который должен предотвращать что-то подобное, но, похоже, это не так (или, скорее, мое понимание, вероятно, было неправильным).
Что я делаю здесь неправильно, или, скорее, - как я могу лучше всего реализоватьэтот цикл без его оптимизации, с наименьшим влиянием на общую производительность?
Я знаю, что мог бы использовать #pragma optimize ("", off), но (кроме как в примере выше), в моем конечном кодеЯ бы очень хотел, чтобы этот вызов был встроен в более крупную функцию по соображениям производительности.Кажется, что эта #pragma, как правило, предотвращает встраивание.
Цени любые мысли!
Спасибо