Я использую C11 * atomics для управления перечислением состояний между несколькими потоками. Код напоминает следующее:C11 и C++ 11 atomics: семантика семантики получения и памяти
static _Atomic State state;
void setToFoo(void)
{
atomic_store_explicit(&state, STATE_FOO, memory_order_release);
}
bool stateIsBar(void)
{
return atomic_load_explicit(&state, memory_order_acquire) == STATE_BAR;
}
This монтирует (для ARM Cortex-M4) в:
<setToFoo>:
ldr r3, [pc, #8]
dmb sy ; Memory barrier
movs r2, #0
strb r2, [r3, #0] ; store STATE_FOO
bx lr
.word 0x00000000
<stateIsBar>:
ldr r3, [pc, #16]
ldrb r0, [r3, #0] ; load state
dmb sy ; Memory barrier
sub.w r0, r0, #2 ; Comparison and return follows
clz r0, r0
lsrs r0, r0, #5
bx lr
.word 0x00000000
Почему заборы, помещенные до выпуск и после приобретаемой? Моя ментальная модель предполагала, что после после будет выпущен барьер (для «распространения» сохраняемой переменной и всех других магазинов в другие потоки) и до приобретать (получать все предыдущие магазины из других потоков).
* В то время как этот конкретный пример приведен в С11, ситуация идентична в C++ 11, так как два одни и те же понятия (и даже те же перечислений), когда речь идет о заказе памяти. gcc
и g++
испускают тот же машинный код в этой ситуации. См. http://en.cppreference.com/w/c/atomic/memory_order и http://en.cppreference.com/w/cpp/atomic/memory_order
В 'stateIsBar (аннулируются)', вы имели в виду, чтобы 'return' это выражение? Потому что, как написано, это функция без оператора return, которая не возвращает void. Он должен скомпилировать одну команду возврата (на самом деле, требуется еще и барьер памяти, но не нагрузка). –
Правильно - спасибо за ловушку опечатки. –