std:: atomic_thread_fence
|
Definido en el encabezado
<atomic>
|
||
|
extern
"C"
void
atomic_thread_fence
(
std::
memory_order
order
)
noexcept
;
|
(desde C++11) | |
Establece el orden de sincronización de memoria de accesos no atómicos y atómicos relajados, según lo indicado por order , sin una operación atómica asociada. Sin embargo, nótese que se requiere al menos una operación atómica para configurar la sincronización, como se describe a continuación.
Contenidos |
Sincronización atómica de barreras
Una barrera de liberación
F
en el hilo
A
se sincroniza-con la operación atómica de
adquisición
Y
en el hilo
B
, si
-
existe un almacenamiento atómico
X(con cualquier orden de memoria), -
Ylee el valor escrito porX(o el valor que sería escrito por la secuencia de liberación encabezada porXsiXfuera una operación de liberación), -
Festá secuenciado-antes deXen el hiloA.
En este caso, todas las operaciones de almacenamiento no atómicas y atómicas relajadas que están
secuenciadas-antes
F
en el hilo
A
ocurrirán
antes-que
todas las operaciones de carga no atómicas y atómicas relajadas de las mismas ubicaciones realizadas en el hilo
B
después de
Y
.
Sincronización con barreras atómicas
Una operación atómica
de liberación
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 orden de memoria), -
Ylee el valor escrito porX(o por la secuencia de liberación encabezada por X ), -
Yestá secuenciado-antes deFen el hiloB.
En este caso, todas las operaciones de almacenamiento no atómicas y atómicas relajadas que están
secuenciadas-antes
X
en el hilo
A
ocurrirán
antes-que
todas las operaciones de carga no atómicas y atómicas relajadas desde las mismas ubicaciones realizadas en el hilo
B
después de
F
.
Sincronización fence-fence
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 orden de memoria) que modificaMen el hiloA, -
FAestá secuenciado-antes deXen el hiloA, -
existe una lectura atómica
Y(con cualquier orden de memoria) en el hiloB, -
Ylee el valor escrito porX(o el valor que sería escrito por la secuencia de liberación encabezada porXsiXfuera una operación de liberación), -
Yestá secuenciado-antes deFBen el hiloB.
En este caso, todas las operaciones de almacenamiento no atómicas y atómicas relajadas que están
secuenciadas-antes
FA
en el hilo
A
ocurrirán
antes-que
todas las operaciones de carga no atómicas y atómicas relajadas de las mismas ubicaciones realizadas en el hilo
B
después de
FB
.
Dependiendo del valor del parámetro order , los efectos de esta llamada son:
- Cuando order == std:: memory_order_relaxed , no hay efectos.
- Cuando order == std:: memory_order_acquire o order == std:: memory_order_consume , es una barrera de adquisición.
- Cuando order == std:: memory_order_release , es una barrera de liberación.
- Cuando order == std:: memory_order_acq_rel , es tanto una barrera de liberación como de adquisición.
- Cuando order == std:: memory_order_seq_cst , es una barrera de ordenación secuencialmente consistente de adquisición y liberación.
Parámetros
| order | - | el orden de memoria ejecutado por esta barrera |
Notas
En x86 (incluyendo x86-64),
atomic_thread_fence
las funciones no emiten instrucciones de CPU y solo afectan el movimiento de código en tiempo de compilación, excepto para
std
::
atomic_thread_fence
(
std::
memory_order_seq_cst
)
.
atomic_thread_fence
impone restricciones de sincronización más fuertes que una operación de almacenamiento atómico con el mismo
std::memory_order
. Mientras que una operación de almacenamiento-liberación atómica evita que todas las lecturas y escrituras anteriores se muevan más allá del almacenamiento-liberación, una
atomic_thread_fence
con ordenamiento
std::
memory_order_release
evita que todas las lecturas y escrituras anteriores se muevan más allá de todos los almacenamientos posteriores.
La sincronización fence-fence puede utilizarse 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 entre 0 y 3 valores ya calculados. 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 resultar ser -1, algunos o todos ellos. // 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
Escanee un arreglo de buzones de correo, y procese solo los destinados a nosotros, sin sincronización innecesaria. Este ejemplo utiliza sincronización con barrera atómica.
const int num_mailboxes = 32; std::atomic<int> mailbox_receiver[num_mailboxes]; std::string mailbox_data[num_mailboxes]; // Los hilos escritores actualizan datos compartidos no atómicos // y luego actualizan 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 sincronizar con uno. for (int i = 0; i < num_mailboxes; ++i) if (std::atomic_load_explicit(&mailbox_receiver[i], std::memory_order_relaxed) == my_id) { // sincronizar con solo un escritor std::atomic_thread_fence(std::memory_order_acquire); // garantizado observar todo lo realizado en el hilo escritor // antes del atomic_store_explicit() do_work(mailbox_data[i]); }
Véase también
|
(C++11)
|
define las restricciones de ordenamiento de memoria para la operación atómica dada
(enum) |
|
(C++11)
|
barrera entre un hilo y un manejador de señales ejecutado en el mismo hilo
(function) |
|
Documentación C
para
atomic_thread_fence
|
|