Si se usa una sola variable atómica y std::memory_order_seq_cst, ¿se garantiza que las operaciones no atómicas no se reordenarán?

Por ejemplo, si tengo

std::atomic<bool> quux = {false};

void foo() {
    bar();
    quux.store(true, std::memory_order_seq_cst);
    moo();
}

Se garantiza bar() que no se reordenará después de la llamada de store, y moo() no se reordenará antes de la llamada de store, siempre que use {{X4} }, al menos desde la perspectiva de otro hilo?

O, para ponerlo en código, ¿son válidos los siguientes supuestos si se ejecutan desde otro hilo?

if(quux.load(std::memory_order_seq_cst) == true) {
   // bar guaranteed to be called; its side-effects are visible
   // moo might have been called, but is not guaranteed to
} else {
   // bar might have been called, but is not guaranteed to
   // moo might have been called, but is not guaranteed to
}

Tenga en cuenta que supongo que ni bar ni moo usan operaciones atómicas, mutexes, bloqueos, cercas u otras funciones de sincronización.

5
Zeta 27 dic. 2016 a las 12:13

3 respuestas

La mejor respuesta

Si se usa una sola variable atómica y std::memory_order_seq_cst, ¿se garantiza que las operaciones no atómicas no se reordenarán?

El estándar es bastante claro en este http://en.cppreference.com/w/cpp / atomic / memory_order:

memory_order_seq_cst Cualquier operación con este orden de memoria es tanto una operación de adquisición como una operación de liberación , además de que existe un único orden total en el que todos los hilos observan todas las modificaciones en el mismo orden

memory_order_acquire Una operación de carga con este orden de memoria realiza la operación de adquisición en la ubicación de memoria afectada: no se pueden reordenar lecturas o escrituras en el hilo actual antes de esta carga .

memory_order_release Una operación de tienda con este orden de memoria realiza la operación de liberación: no se pueden reordenar lecturas o escrituras en el hilo actual después de esta tienda .

En otras palabras, no se pueden reordenar cargas o almacenes (tanto atómicos como no atómicos) alrededor de las operaciones memory_order_seq_cst.


bar() garantiza que no se reordenará después de la llamada de la tienda, y moo() no se reordenará antes de la llamada de la tienda, siempre que use std :: memory_order_seq_cst, al menos desde la perspectiva de otro ¿hilo?

Si las definiciones de bar y moo no están disponibles en la unidad de traducción actual, el compilador supone que estas funciones cargan la memoria y / o tienen efectos secundarios (hacen E / S o se almacenan en la memoria), y, por lo tanto, no se puede reordenar alrededor de las operaciones memory_order_seq_cst.

Si las definiciones están disponibles y las funciones no realizan E / S o cargas / almacenes de memoria, se pueden reordenar. Estas serían funciones puras o funciones que no hacen nada y devuelven void o una constante .

3
Maxim Egorushkin 29 dic. 2016 a las 11:47

Debido a que se utiliza el orden de memoria más estricto, las funciones bar y moo no se pueden reordenar antes o antes de la tienda a quux respectivamente.

Su conclusión para el caso if-else no es del todo correcta.

Si la expresión if(quux.load(std::memory_order_seq_cst) == true) se evalúa como verdadera, entonces la barra de funciones definitivamente ya completará su llamada. No se puede determinar el orden de llamada a muu. Podría haber terminado, no iniciado o podría estar en medio de la llamada.

Si la expresión mencionada se evalúa como falsa, entonces no podemos determinar el orden de ambas funciones. Si bien es cierto que en el momento en que la expresión se evalúa como falsa, la función moo aún no se ha llamado, podría llamarse justo después de eso, antes de que la ejecución pase a la cláusula else. Una vez en la cláusula else, el estado de la función moo es el mismo que en el párrafo anterior (no se puede determinar).

-2
2501 29 dic. 2016 a las 13:11

Según el enlace http://en.cppreference.com/w/cpp/atomic/ memory_order vinculado por @Maxim hay un error con respecto a memory_order_seq_cst. El texto anterior se intercambia con memory_order_acq_rel. El texto para memory_order_seq_cst:

Memory_order_seq_cst: una operación de carga con este pedido de memoria realiza una operación de adquisición, una tienda realiza una operación de liberación y lectura-modificación-escritura realiza tanto una operación de adquisición como una operación de liberación, además de que existe un único pedido total en el que todos los hilos observan todas las modificaciones en el mismo orden (ver orden secuencialmente consistente a continuación)

Entonces, en su caso, la operación de la tienda es equivalente a un lanzamiento, lo que significa que moo () se puede reordenar antes de la cerca.

2
Minee 2 mar. 2018 a las 23:17