std::atomic_fetch_add, std::atomic_fetch_add_explicit
De cppreference.com
<tbody>
</tbody>
<tbody class="t-dcl-rev t-dcl-rev-num ">
</tbody><tbody>
</tbody>
<tbody class="t-dcl-rev t-dcl-rev-num ">
</tbody><tbody>
</tbody>
| 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)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. |
Valor de retorno
El valor que precede inmediatamente a los efectos de esta función en el orden de modificación de *obj.
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);
}
|
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
Ejecuta este código
#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
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 Tse deduce de varios argumentos. |
T se deduce únicamente del argumento atomic.
|
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)
|
(C++11)(C++11) |
Resta un valor no atómico de un objeto atómico y obtiene el valor anterior del objeto atómico. (plantilla de función) |
Documentación de C para atomic_fetch_add, atomic_fetch_add_explicit
| |