Espacios de nombres
Variantes
Acciones

std::atomic_fetch_add, std::atomic_fetch_add_explicit

De cppreference.com
< cpp‎ | atomic
 
 
 
Definido en el archivo de encabezado <atomic>
(1)
template< class T >

T atomic_fetch_add( std::atomic<T>* obj,

                    typename std::atomic<T>::difference_type arg ) noexcept;
template< class T >

T atomic_fetch_add( volatile std::atomic<T>* obj,

                    typename std::atomic<T>::difference_type arg ) noexcept;
(2)
template< class T >

T atomic_fetch_add_explicit( std::atomic<T>* obj,
                             typename std::atomic<T>::difference_type arg,

                             std::memory_order order ) noexcept;
template< class T >

T atomic_fetch_add_explicit( volatile std::atomic<T>* obj,
                             typename std::atomic<T>::difference_type arg,

                             std::memory_order order ) noexcept;

Realiza una suma atómica. Atómicamente suma arg al valor al que apunta obj y devuelve el valor que obj tenía previamente. La operación se realiza como si se ejecutara lo siguiente:

1) obj->fetch_add(arg)
2) obj->fetch_add(arg, order)

Contenido

[editar] Parámetros

obj - Puntero al objeto atómico a modificar.
arg - El valor a sumar al valor almacenado en el objeto atómico.
order - El orden de sincronización de la memoria para esta operación: todos los valores están permitidos.

[editar] Valor de retorno

El valor que precede inmediatamente a los efectos de esta función en el orden de modificación de *obj.

[editar] Posible implementación

template< class T >
T atomic_fetch_add( std::atomic<T>* obj, typename std::atomic<T>::difference_type arg )
{
    return obj->fetch_add(arg);
}

[editar] Ejemplo

Cerrojos de un solo-escritor/múltiples-lectores pueden hacerse con fetch_add. Ten en cuenta que esta implementación simplista no está libre de bloqueo

#include <string>
#include <thread>
#include <vector>
#include <iostream>
#include <atomic>
#include <chrono>
 
// significado de cnt:
// 5: no hay lectores ni escritores activos.
// 1...4: hay 4 ... 1 lectores activos, el escritor está bloqueado
// 0: valor temporal entre fetch_sub y fetch_add en el bloqueo del lector
// -1: hay un escritor activo. Los lectores están bloqueados.
const int N = 5; // se permiten cuatro lectores concurrentes
std::atomic<int> cnt(N);
 
std::vector<int> data;
 
void lector(int id)
{
    for(;;)
    {
        // bloquear
        while(std::atomic_fetch_sub(&cnt, 1) <= 0)
            std::atomic_fetch_add(&cnt, 1);
        // read
        if(!data.empty())
            std::cout << (  "lector " + std::to_string(id)
                          + " ve " + std::to_string(*data.rbegin()) + '\n');
        if(data.size() == 25)
            break;
        // desbloquear
        std::atomic_fetch_add(&cnt, 1);
        // pausa
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
}
 
void escritor()
{
    for(int n = 0; n < 25; ++n)
    {
        // bloquear
        while(std::atomic_fetch_sub(&cnt, N+1) != N)
            std::atomic_fetch_add(&cnt, N+1);
        // escribir
        data.push_back(n);
        std::cout << "escritor empujó al final " << n << '\n';
        // desbloquear
        std::atomic_fetch_add(&cnt, N+1);
        // pausa
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
}
 
int main()
{
    std::vector<std::thread> v;
    for (int n = 0; n < N; ++n) {
        v.emplace_back(lector, n);
    }
    v.emplace_back(escritor);
    for (auto& t : v) {
        t.join();
    }
}

Salida:

escritor empujó al final 0
lector 2 ve 0
lector 3 ve 0
lector 1 ve 0
<...>
lector 2 ve 24
lector 4 ve 24
lector 1 ve 24

[editar] Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
P0558R1 C++11 Se requiere una coincidencia de tipo exacta porque T
se deduce de varios argumentos.
T se deduce únicamente del argumento atomic.

[editar] Véase también

(C++11)
atómicamente agrega el argumento con el valor almacenado en el objeto atómico y obtiene el valor que tenía antes
Original:
atomically adds the argument to the value stored in the atomic object and obtains the value held previously
The text has been machine-translated via Google Translate.
You can help to correct and verify the translation. Click here for instructions.

(función miembro pública de std::atomic) [editar]
Resta un valor no atómico de un objeto atómico y obtiene el valor anterior del objeto atómico.
(plantilla de función) [editar]
Documentación de C para atomic_fetch_add, atomic_fetch_add_explicit