Spec-Zone.ru › C++

std::atomic_thread_fence

Определено в заголовочном файле <atomic>
extern "C" void atomic_thread_fence( std::memory_order order ) noexcept;
(с C++11)

Устанавливает порядок синхронизации памяти для неатомарных и релаксированных атомарных операций, как указано в order, без связанной атомарной операции. Однако следует отметить, что для настройки синхронизации необходима хотя бы одна атомарная операция, как описано ниже.

Синхронизация заграждения-атома

Заграждение выпуска F в потоке A синхронизируется с атомарной операцией захвата Y в потоке B, если

  • существует атомарное сохранение X (с любым порядком памяти),
  • Y считывает значение, записанное X (или значение, которое было бы записано последовательностью выпуска, возглавляемой X, если X была операцией выпуска),
  • F предшествует X в потоке A.

В этом случае все неатомарные и релаксированные атомарные сохранения, которые предшествуют F в потоке A, будут происходить до всех неатомарных и релаксированных атомарных чтений из тех же расположений, выполненных в потоке B после Y.

Синхронизация атомарного заграждения

Атомарная операция выпуска X в потоке A синхронизируется с заграждением захвата F в потоке B, если

  • существует атомарное чтение Y (с любым порядком памяти),
  • Y считывает значение, записанное X (или значение, которое было бы записано последовательностью выпуска, возглавляемой X),
  • Y предшествует F в потоке B.

В этом случае все неатомарные и релаксированные атомарные сохранения, которые предшествуют X в потоке A, будут происходить до всех неатомарных и релаксированных атомарных чтений из тех же расположений, выполненных в потоке B после F.

Синхронизация заграждения-заграждения

Заграждение выпуска FA в потоке A синхронизируется с заграждением захвата FB в потоке B, если

  • существует атомарный объект M,
  • существует атомарная запись X (с любым порядком памяти), которая изменяет M в потоке A,
  • FA предшествует X в потоке A,
  • существует атомарное чтение Y (с любым порядком памяти) в потоке B,
  • Y считывает значение, записанное X (или значение, которое было бы записано последовательностью выпуска, возглавляемой X, если X была операцией выпуска),
  • Y предшествует FB в потоке B.

В этом случае все неатомарные и релаксированные атомарные сохранения, которые предшествуют FA в потоке A, будут происходить до всех неатомарных и релаксированных атомарных чтений из тех же расположений, выполненных в потоке B после FB.

Параметры

order - порядок памяти, выполняемый этим заграждением

Возвращаемое значение

(ничего)

Примечания

На x86 (включая x86-64), atomic_thread_fence функции не выдают команд процессора и влияют только на перемещение кода на этапе компиляции, за исключением std::atomic_thread_fence(std::memory_order::seq_cst).

atomic_thread_fence накладывает более строгие ограничения синхронизации, чем атомарная операция сохранения с тем же std::memory_order. В то время как атомарная операция сохранения-выпуска предотвращает перемещение всех предшествующих чтений и записей мимо операции сохранения-выпуска, atomic_thread_fence с memory_order_release порядком предотвращает перемещение всех предшествующих чтений и записей мимо всех последующих сохранений.

Синхронизацию заграждения-заграждения можно использовать для добавления синхронизации к последовательности нескольких релаксированных атомарных операций, например:

// Global
std::string computation(int);
void print(std::string);
 
std::atomic<int> arr[3] = {-1, -1, -1};
std::string data[1000]; //non-atomic data
 
// Thread A, compute 3 values.
void ThreadA(int v0, int v1, int v2)
{
//  assert(0 <= v0, v1, v2 < 1000);
    data[v0] = computation(v0);
    data[v1] = computation(v1);
    data[v2] = computation(v2);
    std::atomic_thread_fence(std::memory_order_release);
    std::atomic_store_explicit(&arr[0], v0, std::memory_order_relaxed);
    std::atomic_store_explicit(&arr[1], v1, std::memory_order_relaxed);
    std::atomic_store_explicit(&arr[2], v2, std::memory_order_relaxed);
}
 
// Thread B, prints between 0 and 3 values already computed.
void ThreadB()
{
    int v0 = std::atomic_load_explicit(&arr[0], std::memory_order_relaxed);
    int v1 = std::atomic_load_explicit(&arr[1], std::memory_order_relaxed);
    int v2 = std::atomic_load_explicit(&arr[2], std::memory_order_relaxed);
    std::atomic_thread_fence(std::memory_order_acquire);
//  v0, v1, v2 might turn out to be -1, some or all of them.
//  Otherwise it is safe to read the non-atomic data because of the fences:
    if (v0 != -1)
        print(data[v0]);
    if (v1 != -1)
        print(data[v1]);
    if (v2 != -1)
        print(data[v2]);
}

Пример

Просмотрите массив почтовых ящиков и обработайте только те, которые предназначены для нас, без ненужной синхронизации. В этом примере используется синхронизация атомарного заграждения.

const int num_mailboxes = 32;
std::atomic<int> mailbox_receiver[num_mailboxes];
std::string mailbox_data[num_mailboxes];
 
// The writer threads update non-atomic shared data 
// and then update mailbox_receiver[i] as follows:
mailbox_data[i] = ...;
std::atomic_store_explicit(&mailbox_receiver[i], receiver_id, std::memory_order_release);
 
// Reader thread needs to check all mailbox[i], but only needs to sync with one.
for (int i = 0; i < num_mailboxes; ++i)
    if (std::atomic_load_explicit(&mailbox_receiver[i],
        std::memory_order_relaxed) == my_id)
    {
        // synchronize with just one writer
        std::atomic_thread_fence(std::memory_order_acquire);
        // guaranteed to observe everything done in the writer thread
        // before the atomic_store_explicit()
        do_work(mailbox_data[i]);
    }

См. также

memory_order
(C++11)
определяет ограничения порядка памяти для данной атомарной операции
(перечисление)
atomic_signal_fence
(C++11)
заграждение между потоком и обработчиком сигналов, выполняемым в том же потоке
(функция)
C документация для atomic_thread_fence

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/atomic/atomic_thread_fence

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API