6.52 Встроенные функции для операций с атомными данными, учитывающие модель памяти
Следующие встроенные функции примерно соответствуют требованиям модели памяти C++11. Многие из них похожи на встроенные функции с префиксом ‘__sync’, но все они также имеют параметр модели памяти. Все они идентифицируются по префиксу ‘__atomic’, и большинство из них перегружены так, что работают с несколькими типами.
GCC допускает любые целочисленные скалярные типы или указатели длиной 1, 2, 4 или 8 байт. Целочисленные типы длиной 16 байт также допускаются, если ‘__int128’ (см. __int128) поддерживается архитектурой.
Архитектуры целевых платформ рекомендуют предоставлять собственные шаблоны для каждой из этих встроенных функций. Если целевая платформа не указана, используются исходные атомарные встроенные функции ‘__sync’ без учёта модели памяти, а также любые необходимые синхронизирующие барьеры, чтобы достичь правильного поведения. Выполнение в этом случае подчиняется тем же ограничениям, что и для этих встроенных функций.
Если нет шаблона или механизма для предоставления последовательности инструкций без блокировки, вызов передаётся внешней процедуре с теми же параметрами для решения во время выполнения.
Четыре неарифметические функции (load, store, exchange и compare_exchange) также имеют общую версию. Эта общая версия работает с любым типом данных. Если размер типа данных соответствует одному из целочисленных размеров, для которых может быть доступна поддержка без блокировки, общая версия использует встроенную функцию без блокировки. В противном случае вызов делегируется внешней процедуре для решения во время выполнения. Этот внешний вызов имеет тот же формат, с добавлением параметра ‘size_t’ в качестве первого параметра, указывающего на размер объекта, на который указывает указатель. Все объекты должны иметь одинаковый размер.
Существует 6 различных моделей памяти, которые можно указать. Они соответствуют тем же именам в стандарте C++11. Подробные определения см. там или в вики GCC по атомарной синхронизации. Эти модели памяти интегрируют как барьеры для перемещения кода, так и требования к синхронизации с другими потоками. Они перечислены приблизительно в порядке возрастания силы. Также возможно использовать специфичные для целевой платформы флаги для флагов модели памяти, такие как Hardware Lock Elision.
__ATOMIC_RELAXED- Нет барьеров и синхронизации.
__ATOMIC_CONSUME- Только зависимость данных для барьера и синхронизации с другим потоком.
__ATOMIC_ACQUIRE- Барьер для подъёма кода и синхронизация с операциями хранения (или более сильными) с семантикой выпуска из другого потока.
__ATOMIC_RELEASE- Барьер для опускания кода и синхронизация с операциями загрузки (или более сильными) с семантикой приобретения из другого потока.
__ATOMIC_ACQ_REL- Полный барьер в обоих направлениях и синхронизация с загрузкой приобретения и операциями хранения выпуска в другом потоке.
__ATOMIC_SEQ_CST- Полный барьер в обоих направлениях и синхронизация с загрузкой приобретения и операциями хранения выпуска во всех потоках.
При реализации шаблонов для этих встроенных функций параметр модели памяти можно игнорировать, если шаблон реализует самую жёсткую __ATOMIC_SEQ_CST модель. Любые другие модели памяти будут выполняться корректно с этой моделью, но могут выполняться не так эффективно, как с более подходящей реализацией требований релаксации.
Обратите внимание, что стандарт C++11 допускает определение параметра модели памяти во время выполнения, а не во время компиляции. Эти встроенные функции отображают любое значение времени выполнения в __ATOMIC_SEQ_CST вместо вызова библиотеки времени выполнения или вставки оператора switch. Это соответствует стандарту, безопасно и является на данный момент наиболее простым подходом.
Параметр модели памяти — целое число со знаком, но только младшие 8 бит зарезервированы для модели памяти. Остальная часть целого числа со знаком зарезервирована для будущего использования и должна быть равна 0. Использование предопределённых атомных значений гарантирует правильное использование.
Эта встроенная функция реализует операцию атомарной загрузки. Она возвращает содержимое
*ptr.Допустимые варианты моделей памяти —
__ATOMIC_RELAXED,__ATOMIC_SEQ_CST,__ATOMIC_ACQUIRE, и__ATOMIC_CONSUME.
Это общая версия атомарной загрузки. Она возвращает содержимое
*ptr в*ret.
Эта встроенная функция реализует операцию атомарного хранения. Она записывает val в
*ptr.Допустимые варианты моделей памяти —
__ATOMIC_RELAXED,__ATOMIC_SEQ_CST, и__ATOMIC_RELEASE.
Это общая версия атомарного хранения. Она сохраняет значение
*val в*ptr.
Эта встроенная функция реализует операцию атомарного обмена. Она записывает val в
*ptr и возвращает предыдущее содержимое*ptr.Допустимые варианты моделей памяти —
__ATOMIC_RELAXED,__ATOMIC_SEQ_CST,__ATOMIC_ACQUIRE,__ATOMIC_RELEASE, и__ATOMIC_ACQ_REL.
Это общая версия атомарного обмена. Она сохраняет содержимое
*val в*ptr. Исходное значение*ptr копируется в*ret.
Эта встроенная функция реализует операцию атомарного сравнения и обмена. Она сравнивает содержимое
*ptr с содержимым*expected и, если они равны, записывает desired в*ptr. Если они не равны, текущее содержимое*ptr записывается в*expected. weak — true для слабого сравнения и обмена, и false для сильной версии. Многие целевые платформы предлагают только сильную версию и игнорируют параметр. В случае сомнений используйте сильную версию.Возвращает true, если desired записано в
*ptr, и выполнение считается соответствующим модели памяти, указанной success_memmodel. Нет ограничений на модель памяти, которую можно использовать здесь.В противном случае возвращает false, и выполнение считается соответствующим failure_memmodel. Эта модель памяти не может быть
__ATOMIC_RELEASEили__ATOMIC_ACQ_REL. Она также не может быть сильнее, чем модель, указанная success_memmodel.
Эта встроенная функция реализует общую версию
__atomic_compare_exchange. Функция практически идентична__atomic_compare_exchange_n, за исключением того, что желаемое значение также является указателем.
Эти встроенные функции выполняют операцию, предложенную названием, и возвращают результат операции. То есть,
{ *ptr op= val; return *ptr; }Все модели памяти допустимы.
Эти встроенные функции выполняют операцию, предложенную названием, и возвращают значение, которое ранее находилось в
*ptr. То есть,{ tmp = *ptr; *ptr op= val; return tmp; }Все модели памяти допустимы.
Эта встроенная функция выполняет атомарную операцию test-and-set для байта по адресу
*ptr. Байт устанавливается на некоторое реализационно-определённое ненулевое значение «установки», и возвращаемое значение равноtrueтогда и только тогда, когда предыдущее содержимое было «установлено». Она должна использоваться только для операндов типаboolилиchar. Для других типов может быть установлена только часть значения.Все модели памяти допустимы.
Эта встроенная функция выполняет атомарную операцию очистки для
*ptr. После операции*ptr содержит 0. Она должна использоваться только для операндов типаboolилиcharи в сочетании с__atomic_test_and_set. Для других типов может быть очищена только часть. Если тип неboolпредпочтительнее использовать__atomic_store.Допустимые варианты моделей памяти —
__ATOMIC_RELAXED,__ATOMIC_SEQ_CST, и__ATOMIC_RELEASE.
Эта встроенная функция действует как синхронизирующий барьер между потоками на основе заданной модели памяти.
Все порядки памяти допустимы.
Эта встроенная функция действует как синхронизационная преграда между потоком и обработчиками сигналов, основанными в том же потоке.
Все порядки памяти допустимы.
Эта встроенная функция возвращает true, если объекты размером в size байт всегда генерируют атомарные инструкции без блокировки для целевой архитектуры. size должен разрешаться как константа времени компиляции, а результат также разрешается как константа времени компиляции.
ptr — это необязательный указатель на объект, который может использоваться для определения выравнивания. Значение 0 указывает, что следует использовать типичное выравнивание. Компилятор также может игнорировать этот параметр.
if (_atomic_always_lock_free (sizeof (long long), 0))
Эта встроенная функция возвращает true, если объекты размером в size байт всегда генерируют атомарные инструкции без блокировки для целевой архитектуры. Если не известно, что это безблокировочная операция, вызывается внутренняя процедура под названием
__atomic_is_lock_free.ptr — это необязательный указатель на объект, который может использоваться для определения выравнивания. Значение 0 указывает, что следует использовать типичное выравнивание. Компилятор также может игнорировать этот параметр.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/_005f_005fatomic-Builtins.html