32 Atomic operations library [atomics]

32.4 Order and consistency [atomics.order]

namespace std {
  enum memory_order {
    memory_order_relaxed, memory_order_consume, memory_order_acquire,
    memory_order_release, memory_order_acq_rel, memory_order_seq_cst
  };
}

Перечисление memory_­order определяет подробный регулярный (неатомарный) порядок синхронизации памяти, как определено в, [intro.multithread] и может предусматривать порядок операций. Его перечисляемые значения и их значения следующие:

  • memory_­order_­relaxed: никакая операция не заказывает память.

  • memory_­order_­release, memory_­order_­acq_­relи memory_­order_­seq_­cst: операция сохранения выполняет операцию освобождения затронутой области памяти.

  • memory_­order_­consume: операция загрузки выполняет операцию потребления в затронутой области памяти. [ Note: Предпочтение memory_­order_­acquire, которое обеспечивает более сильные гарантии, чем memory_­order_­consume. Реализации сочли невозможным обеспечить производительность лучше, чем у memory_­order_­acquire. Пересмотр спецификации находится на рассмотрении. ] end note

  • memory_­order_­acquire, memory_­order_­acq_­relи memory_­order_­seq_­cst: операция загрузки выполняет операцию получения в затронутой области памяти.

[ Note: Указание атомарных операций memory_­order_­relaxed ослаблено в отношении упорядочения памяти. Реализации должны по-прежнему гарантировать, что любой заданный атомарный доступ к конкретному атомарному объекту будет неделимым по отношению ко всем другим атомарным доступам к этому объекту. ] end note

Атомарная операция, A которая выполняет операцию выпуска над атомарным объектом, M синхронизируется с атомарной операцией, B которая выполняет операцию получения M и берет свое значение из любого побочного эффекта в последовательности выпуска, озаглавленной A.

Должен быть единый общий порядок S для всех memory_­order_­seq_­cst операций, соответствующий порядку «происходит до» и порядкам модификации для всех затронутых местоположений, так что каждая memory_­order_­seq_­cst операция, B которая загружает значение из атомарного объекта, M наблюдает одно из следующих значений:

  • результат последней модификации A из того, M что предшествует B в S, если она существует, или

  • если A существует, результат некоторой модификации M этого не происходит memory_­order_­seq_­cst и не происходило раньше A, или

  • если A не существует, результат некоторой модификации M этого не существует memory_­order_­seq_­cst.

[ Note: Хотя явно не требуется S включать блокировки, его всегда можно расширить до порядка, который включает операции блокировки и разблокировки, поскольку упорядочение между ними уже включено в порядок «происходит до». ] end note

Для атомарной операции, B которая считывает значение атомарного объекта M, если есть memory_­order_­seq_­cst забор, X упорядоченный ранее B, то B наблюдает либо последнюю memory_­order_­seq_­cst модификацию M предыдущего X в общем порядке, S либо более позднюю модификацию M в его порядке модификации.

Для атомарных операций A и B для атомарного объекта M, где A модифицирует M и B принимает свое значение, если есть memory_­order_­seq_­cst ограждение X , которое A упорядочено до X и B следует X за ним S, то B наблюдает либо эффекты, A либо последующие модификации M в порядке его модификации.

Для атомарных операций A и B на атомарном объекте M, где A модифицирует M и B принимает свое значение, если есть memory_­order_­seq_­cst ограждения, X и Y такое, что A упорядочено до X, Y упорядочено до Bи X предшествует Y в S, то B наблюдает либо эффекты, A либо более позднюю модификацию M в порядке его модификации .

Для атомных модификаций A и B атомного объекта M, B происходит позже , чем A в порядке модификации , M если:

  • есть memory_­order_­seq_­cst забор X таким образом, что A секвенировали до того X, и X предшествует B в S, или

  • есть memory_­order_­seq_­cst забор Y таким образом, что Y секвенировали до того B, и A предшествует Y в S, или

  • есть memory_­order_­seq_­cst заборы X и Y такие, что A упорядочены до X, Y упорядочены до Bи X предшествуют Y в S.

[ Note: memory_­order_­seq_­cst обеспечивает последовательную согласованность только для программы, которая свободна от гонок данных и использует исключительно memory_­order_­seq_­cst операции. Любое использование более слабого порядка приведет к аннулированию этой гарантии, если не будут приняты особые меры предосторожности. В частности, memory_­order_­seq_­cst заборы обеспечивают полный порядок только самих заборов. Как правило, ограждения не могут использоваться для восстановления последовательной согласованности атомарных операций с более слабыми спецификациями упорядочивания. ] end note

Реализации должны гарантировать, что не вычисляются «неожиданные» значения, которые циклически зависят от их собственных вычислений.

[ Note: Например, x и y изначально равна нулю,

// Thread 1:
r1 = y.load(memory_order_relaxed);
x.store(r1, memory_order_relaxed);
// Thread 2:
r2 = x.load(memory_order_relaxed);
y.store(r2, memory_order_relaxed);

не следует производить r1 == r2 == 42, так как хранение от 42 до y возможно только при хранении в x магазинах 42, которое циклически зависит от магазина для y хранения 42. Обратите внимание, что без этого ограничения такое выполнение возможно. ]end note

[ Note: Рекомендация аналогичным образом запрещает r1 == r2 == 42 в следующем примере с снова x и y снова с нулевым значением:

// Thread 1:
r1 = x.load(memory_order_relaxed);
if (r1 == 42) y.store(42, memory_order_relaxed);
// Thread 2:
r2 = y.load(memory_order_relaxed);
if (r2 == 42) x.store(42, memory_order_relaxed);

end note]

Атомарные операции чтения-изменения-записи всегда должны считывать последнее значение (в порядке модификации), записанное перед записью, связанной с операцией чтения-изменения-записи.

Реализации должны делать атомарные хранилища видимыми для атомарных загрузок в течение разумного промежутка времени.

template <class T> T kill_dependency(T y) noexcept;

Effects: Аргумент не carry a dependency соответствует возвращаемому значению.

Returns: y.