Кодовая база имеет макрос COMPILER_BARRIER
, определенный как __asm__ volatile("" ::: "memory")
. Цель макроса состоит в том, чтобы предотвратить перекомпилирование компилятора при чтении и записи через барьер. Обратите внимание, что это явно барьер компилятора, а не уровень памяти уровня памяти.Что такое атомный API C++ 11, эквивалентный `` `__asm__ volatile (" ":::" memory ")` ``
Как есть, это довольно портативно, поскольку в сборке AssemblerTemplate нет фактических инструкций по сборке, только volatile
и clobber memory
. Итак, до тех пор, пока компилятор отличает синтаксис расширенного Asm от GCC, он должен работать нормально. Тем не менее, мне любопытно, как правильно выразить это, если это возможно, в API-интерфейсе C++ 11 atomics.
Возможно, что это была правильная идея: atomic_signal_fence(memory_order_acq_rel);
.
Мои рассуждения в том, что:
- Из
<atomic>
API, толькоatomic_signal_fence
иatomic_thread_fence
не нужен адрес памяти от которой работать. atomic_thread_fence
влияет на порядок памяти, который нам не нужен для барьера компилятора.- Клобук
memory
в расширенной версии Asm не проводит различия между чтением и записью, поэтому нам кажется, что мы хотим как семантики как получить, так и освободить, так что, как минимум, требуетсяmemory_order_acq_rel
. memory_order_seq_cst
кажется ненужным, так как мы не требуем полного порядка по потокам - нас интересует только секвенирование команд в текущем потоке.
Можно ли выразить эквивалент __asm__ volatile("" ::: "memory")
полностью портативно с помощью API атомизации C++ 11? Если да, то atomic_signal_fence
правильный API для использования? Если да, то какой аргумент порядка памяти подходит/необходим здесь?
Или я в сорняках здесь, и есть лучший способ приблизиться к этому?
'atomic_signal_fence' гарантирует только порядок между потоком и обработчиком сигнала, работающим в том же потоке. Аналогично, 'atomic_thread_fence' применяется только к упорядочению между потоками. Если вы пытаетесь гарантировать заказ между двумя другими контекстами, то ни один из них не переносится. Например, в Windows 'atomic_signal_fence' ничего не нужно делать, потому что Windows не поддерживает асинхронные сигналы. –
@RossRidge - Мне было немного странно использовать atom_signal_fence, потому что, как вы указываете, здесь нет сигналов. Но это было единственное, что «сработало», по моей схеме выше. Я не видел ни одного языка в стандарте, хотя это позволило бы вызывать atom_signal_fence, если бы реализация не имела асинхронных сигналов. В 28.9.7 стандарта C++ 14 указано, что «оптимизация компилятора и переупорядочивание нагрузок и хранилищ запрещены так же, как и с atomic_thread_fence, но инструкции по аппаратным ограждениям ...». – acm
Это информативная (ненормативная) заметка, она не создает ограничений на реализацию. В стандарте не предусмотрен какой-либо язык, который позволил бы вам зависеть от него как нечто большее, чем «эквивалентное atom_thread_fence (order)», за исключением того, что результирующие ограничения упорядочения устанавливаются только между потоком и обработчиком сигнала, выполненным в том же потоке » , Заметим также, что 'atomic_thread_fence' определяется в терминах атомных операций над атомными объектами, как определено стандартом. Поэтому, если вы не используете типы 'std :: atomic', то ни одна из функций не будет работать. –