std::atomic_thread_fence
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.
Contenido |
[editar]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ónY 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 Asucederá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.
[editar]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
- existe una lectura atómica Y (con cualquier ordenamiento de memoria);
- Y lee el valor escrito por X (o por la secuencia de liberación encabezada por X);
- Y es secuenciada antes que F en el hilo B.
En este caso, los almacenamientos no atómicos y atómicos relajados que son secuenciados-antes que X en el hilo Asucederá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.
[editar]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 Asucederá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.
[editar]Parámetros
order | - | El ordenamiento de memoria ejecutado por esta barrera. |
[editar]Valor de retorno
(Ninguno)
[editar]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:
// Globalstd::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 valoresvoid 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 3void 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]);}}
[editar]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.
constint 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 unofor(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()}}
[editar]Véase también
(C++11) | Define las restricciones del ordenamiento de memoria para la operación atómica dada. (typedef) |
(C++11) | Barrera entre un hilo y un controlador de señales ejecutados en el mismo hilo/subproceso. (función) |
Documentación de C para atomic_thread_fence |