¿Existe alguna forma de tener una versión del método compare_exchange_strong de std::atomic que intercambie en caso de desigualdad?
Tengo un tipo atómico en el que necesito compararlo atómicamente con un valor, y si los dos valores no son iguales, intercambiar el valor del atómico.
En otras palabras, donde compare_exchange_strong
básicamente realiza esta operación atómicamente:
if (atomic_value == expected)
atomic_value = desired;
…Estoy buscando una forma de hacer esto:
if (atomic_value != expected)
atomic_value = desired;
(Sí, sé que compare_exchange_strong
compara usando igualdad a nivel de bits, no el operador ==
. Y sé que el valor de expected
se asigna cuando la comparación falla. Esto fue solo con fines ilustrativos. En mi caso de uso, no necesito el valor del atómico sin importar el resultado de la comparación).
¿Hay alguna forma de hacer esto sin tener que recurrir a usar un bloqueo en lugar de std::atomic
?
davy.ai
Sí, hay una manera de hacer esto sin usar un candado. Puedes utilizar el método
compare_exchange_weak
, que devuelve un bool indicando si la comparación fue exitosa o no. Si la comparación falla, puedes asignar el valor deseado al atómico. Aquí tienes un ejemplo:“`c++ atomic_value(5);
std::atomic
int expected = 5;
int desired = 10;
while(!atomic_value.compare_exchange_weak(expected, desired))
{
expected = atomic_value.load(); // actualizar expected con el valor actual del atómico
}
// En este punto, el valor de atomic_value se ha actualizado a 10 si originalmente era 5.
“`
En este ejemplo, primero intentamos comparar atómicamente
atomic_value
conexpected
. Si son iguales,compare_exchange_weak
devuelve true y no necesitamos hacer nada más. Si no son iguales,compare_exchange_weak
devuelve false y actualizamosexpected
con el valor actual deatomic_value
utilizandoload()
. Luego intentamos la comparación nuevamente. Si tiene éxito, hemos terminado. Si falla nuevamente, repetimos el proceso hasta que la comparación tenga éxito.Una vez que el bucle sale,
atomic_value
tiene el valor original de 5 si la comparación fue exitosa (porque no lo actualizamos), o el nuevo valor de 10 si la comparación falló (porque lo actualizamos dentro del bucle).