Espacios de nombres
Variantes

std::atomic_thread_fence

De cppreference.com
 
 
 
Definido en el archivo de encabezado <atomic>
extern "C" void atomic_thread_fence( std::memory_order order ) noexcept;
(desde C++11)

Establece un ordenamiento de sincronización de memoria de accesos no atómicos y relajados, como se indica por order, sin una operación atómica asociada.

Sincronización de barrera a operación atómica

Una barrera de liberación F en el hilo A se sincroniza con una operación de adquisición Y en el hilo B, si

  • existe un almacenamiento atómico X (con cualquier ordenamiento de memoria);
  • Y lee el valor escrito por X (o el valor sería escrito por la secuencia de liberación encabezada por X si X fuera una operación de liberación);
  • F es secuenciada antes que X en el hilo A.

En este caso, los almacenamientos no atómicos y atómicos relajados que son secuenciados-antes que F en el hilo A sucederán-antes que todas las cargas no atómicas y atómicas relajadas desde las mismas ubicaciones hechas en el hilo B después de Y.

Sincronización de operación atómica a barrera

Una operación de liberación atómica X en el hilo A se sincroniza-con una barrera de adquisición F en el hilo B, si

En este caso, los almacenamientos no atómicos y atómicos relajados que son secuenciados-antes que X en el hilo A sucederán-antes que todas las cargas no atómicas y atómicas relajadas desde las mismas ubicaciones hechas en el hilo B después de F.

Sincronización de barrera a barrera

Una barrera de liberación FA en el hilo A se sincroniza-con una barrera de adquisición FB en el hilo B, si

  • existe un objeto atómico M;
  • existe una escritura atómica X (con cualquier ordenamiento de memoria) que modifica a M en el hilo A;
  • FA es secuenciada antes que X en el hilo A;
  • existe una lectura atómica Y (con cualquier ordenamiento de memoria) en el hilo B;
  • Y lee el valor escrito por X (o el valor sería escrito por la secuencia de liberación encabezada por X si X fuera una operación de liberación);
  • Y es secuenciada antes que FB en el hilo B;

En este caso, los almacenamientos no atómicos y atómicos relajados que son secuenciados-antes que FA en el hilo A sucederán-antes que todas las cargas no atómicas y atómicas relajadas desde las mismas ubicaciones hechas en el hilo B después de FB.

Parámetros

order - El ordenamiento de memoria ejecutado por esta barrera.

Valor de retorno

(Ninguno)

Notas

atomic_thread_fence impone restricciones de sincronización más rígidas que una operación de almacenamiento atómica con el mismo std::memory_order. Mientras que una operación almacenar-liberar evita que todas las escrituras anteriores se muevan más allá de la operación almacenar-liberar, un atomic_thread_fence con ordenamiento memory_order_release evita que todas las escrituras anteriores se muevan más allá de todos los almacenamientos posteriores.

La sincronización de barrera a barrera se puede usar para agregar sincronización a una secuencia de varias operaciones atómicas relajadas, por ejemplo:

// Global
std::string computation(int);
void print( std::string );

std::atomic<int> arr[3] = { -1, -1, -1 };
std::string data[1000]; // datos no atómicos

// Hilo A, calcula 3 valores
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);
}

// Hilo B, imprime valores ya calculados entre 0 y 3
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 podrían ser -1, algunas o todas.
  // de lo contrario es seguro leer los datos no atómicos debido a las barreras:
  if( v0 != -1 ) { print( data[v0] ); }
  if( v1 != -1 ) { print( data[v1] ); }
  if( v2 != -1 ) { print( data[v2] ); }
}

Ejemplo

Escanear una variedad de buzones de correo y procesar solo los que están destinados a nosotros, sin sincronizaciones innecesarias. Este ejemplo usa la sincronización de operación atómica a barrera.

const int num_mailboxes = 32;
std::atomic<int> mailbox_receiver[num_mailboxes];
std::string mailbox_data[num_mailboxes];

// Los hilos escritores actualizan los datos no atómicos compartidos
// y luego actualizan a mailbox_receiver[i] de la siguiente manera
mailbox_data[i] = ...;
std::atomic_store_explicit(&mailbox_receiver[i], receiver_id, std::memory_order_release);

// El hilo lector necesita verificar todos los mailbox[i],
// pero solo necesita sincronizarse con uno
for (int i = 0; i < num_mailboxes; ++i) {
    if (std::atomic_load_explicit(&mailbox_receiver[i], std::memory_order_relaxed) == my_id) {
        std::atomic_thread_fence(std::memory_order_acquire); // sincronizar con solo un escritor
        do_work( mailbox_data[i] ); // garantizado que observa todo lo hecho por el hilo escritor
                                    // antes de atomic_store_explicit()
    }
 }

Véase también

Define las restricciones del ordenamiento de memoria para la operación atómica dada.
(typedef) [editar]
Barrera entre un hilo y un controlador de señales ejecutados en el mismo hilo/subproceso.
(función) [editar]
Documentación de C para atomic_thread_fence