when c++ stl c++11 atomic c++-standard-library

c++ - when - std:: atomic | compare_exchange_weak vs. compare_exchange_strong



std::atomic (2)

No estoy seguro si soy yo el que no entiende o la documentación no está claramente formulada.

El siguiente extracto se ha tomado del borrador más reciente (N3126, sección 29.6):

bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired); bool atomic_compare_exchange_weak(A* object, C * expected, C desired); bool atomic_compare_exchange_strong(volatile A* object, C * expected, C desired); bool atomic_compare_exchange_strong(A* object, C * expected, C desired); bool atomic_compare_exchange_weak_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure); bool atomic_compare_exchange_weak_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure); bool atomic_compare_exchange_strong_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure); bool atomic_compare_exchange_strong_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure); bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure) volatile; bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure); bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure) volatile; bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure); bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile; bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst); bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile; bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst);

Observación: Las débiles operaciones de comparación e intercambio pueden fallar falsamente, es decir, devolver falso al dejar el contenido de la memoria apuntado por lo esperado antes de que la operación sea la misma que la del objeto y la misma que la esperada después la operacion. [Nota: Esta falla falsa habilita la implementación de la comparación e intercambio en una clase más amplia de máquinas, por ejemplo, máquinas condicionadas por la tienda con bloqueo de carga. Una consecuencia de fallas espurias es que casi todos los usos de débiles comparaciones e intercambios estarán en un bucle.

¿Entonces, qué significa esto?

En primer lugar, ''puede'' fallar falsamente ?! ¿Por qué fallaría? ¿Y cómo definen ''mayo''?

En segundo lugar, todavía no tengo idea de cuál es la diferencia entre las funciones con los sufijos "_strong" y "_weak". ¿Alguien podría explicar la diferencia?

EDIT: Eso es lo que he encontrado en libstdc ++ - implementación (atomic_0.h):

bool compare_exchange_weak( __integral_type& __i1, __integral_type __i2, memory_order __m1, memory_order __m2 ) { __glibcxx_assert(__m2 != memory_order_release); __glibcxx_assert(__m2 != memory_order_acq_rel); __glibcxx_assert(__m2 <= __m1); return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1); } bool compare_exchange_strong( __integral_type& __i1, __integral_type __i2, memory_order __m1, memory_order __m2 ) { __glibcxx_assert(__m2 != memory_order_release); __glibcxx_assert(__m2 != memory_order_acq_rel); __glibcxx_assert(__m2 <= __m1); return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1); }


La nota da una pista, refiriéndose a las arquitecturas LL/SC . Del artículo de Wikipedia:

Si se han producido actualizaciones, se garantiza que el condicional de la tienda fallará, incluso si el valor leído por el enlace de carga ha sido restaurado desde entonces. Como tal, un par de LL / SC es más fuerte que una lectura seguida de una comparación e intercambio (CAS), que no detectará actualizaciones si el valor anterior se ha restaurado (consulte el problema ABA).

Las implementaciones reales de LL / SC no siempre tienen éxito si no hay actualizaciones simultáneas en la ubicación de memoria en cuestión. Cualquier evento excepcional entre las dos operaciones, como un cambio de contexto, otro enlace de carga, o incluso (en muchas plataformas) otra operación de carga o almacenamiento, causará que el condicional de la tienda falle falsamente.

En los chips LL / SC, el compare_exchange se implementará en términos de LL / SC, que puede fallar falsamente, por lo que compare_exchange_strong necesita una sobrecarga adicional para volver a intentarlo en caso de falla. Proporcionar compare_exchange_strong y compare_exchange_weak permite al programador decidir si quieren que la biblioteca maneje fallas falsas (en cuyo caso usarían compare_exchange_strong o si quieren manejarla en su propio código (en cuyo caso usarían compare_exchange_weak )


Tiene que ver con el modelo de consistencia de memoria compartida que implementa el hardware. Para aquellas arquitecturas de hardware que implementan algún tipo de modelo de consistencia relajada (por ejemplo, semántica de lanzamiento), las operaciones sólidas a las que se refiere anteriormente pueden tener una gran sobrecarga, y por lo tanto los expertos pueden usar las formas más débiles para implementar algoritmos que funcionan bien también en esas consistencias relajadas arquitecturas

Para más información, ver por ejemplo

http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

Capítulo 12 y Apéndice C en http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html