Namespaces
Variants

std:: atomic

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
atomic
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
Défini dans l'en-tête <atomic>
template < class T >
struct atomic ;
(1) (depuis C++11)
template < class U >
struct atomic < U * > ;
(2) (depuis C++11)
Défini dans l'en-tête <memory>
template < class U >
struct atomic < std:: shared_ptr < U >> ;
(3) (depuis C++20)
template < class U >
struct atomic < std:: weak_ptr < U >> ;
(4) (depuis C++20)
Défini dans l'en-tête <stdatomic.h>
#define _Atomic(T) /* voir ci-dessous */
(5) (depuis C++23)

Chaque instanciation et spécialisation complète du modèle std::atomic définit un type atomique. Si un thread écrit dans un objet atomique pendant qu'un autre thread le lit, le comportement est bien défini (voir le modèle de mémoire pour plus de détails sur les courses de données).

De plus, les accès aux objets atomiques peuvent établir une synchronisation inter-threads et ordonner les accès mémoire non atomiques comme spécifié par std::memory_order .

std::atomic n'est ni copiable ni déplaçable.

La macro de compatibilité _Atomic est fournie dans <stdatomic.h> de telle sorte que _Atomic(T) est identique à std::atomic<T> lorsque les deux sont bien formés.

Il n'est pas spécifié si une déclaration dans l'espace de noms std est disponible lorsque <stdatomic.h> est inclus.

(depuis C++23)

Table des matières

Spécialisations

Modèle principal

Le modèle principal std::atomic peut être instancié avec tout type TriviallyCopyable T satisfaisant à la fois CopyConstructible et CopyAssignable . Le programme est mal formé si l'une des valeurs suivantes est false :

*Note: Since all text content in this HTML fragment consists of C++ code within ` ` tags (which should be treated like ` ` tags), no translation was performed as per the instructions. The structure and formatting remain completely unchanged.*
struct Counters { int a; int b; }; // type défini par l'utilisateur trivialement copiable
std::atomic<Counters> cnt;         // spécialisation pour le type défini par l'utilisateur

std :: atomic < bool > utilise le modèle principal. Il est garanti d'être une structure de disposition standard et possède un destructeur trivial .

Spécialisations partielles

La bibliothèque standard fournit des spécialisations partielles du modèle std::atomic pour les types suivants avec des propriétés supplémentaires que le modèle principal ne possède pas :

2) Spécialisations partielles std::atomic<U*> pour tous les types pointeurs. Ces spécialisations ont une disposition standard , des constructeurs par défaut triviaux, (jusqu'à C++20) et des destructeurs triviaux. En plus des opérations fournies pour tous les types atomiques, ces spécialisations supportent également des opérations arithmétiques atomiques appropriées aux types pointeurs, telles que fetch_add , fetch_sub .
3,4) Spécialisations partielles std :: atomic < std:: shared_ptr < U >> et std :: atomic < std:: weak_ptr < U >> sont fournies pour std::shared_ptr et std::weak_ptr .

Voir std::atomic <std::shared_ptr> et std::atomic <std::weak_ptr> pour plus de détails.

(depuis C++20)

Spécialisations pour les types entiers

Lorsqu'il est instancié avec l'un des types entiers suivants, std::atomic fournit des opérations atomiques supplémentaires appropriées aux types entiers telles que fetch_add , fetch_sub , fetch_and , fetch_or , fetch_xor :

  • Les types de caractères char , char8_t (depuis C++20) , char16_t , char32_t , et wchar_t ;
  • Les types entiers signés standards : signed char , short , int , long , et long long ;
  • Les types entiers non signés standards : unsigned char , unsigned short , unsigned int , unsigned long , et unsigned long long ;
  • Tout type entier supplémentaire requis par les typedefs dans l'en-tête <cstdint> .

De plus, la spécialisation résultante std::atomic< Integral > a une disposition standard , un constructeur par défaut trivial, (jusqu'à C++20) et un destructeur trivial. L'arithmétique des entiers signés est définie pour utiliser le complément à deux ; il n'y a pas de résultats indéfinis.

Spécialisations pour les types à virgule flottante

Lorsqu'instancié avec l'un des types à virgule flottante non qualifiés cv ( float , double , long double et les types à virgule flottante étendus non qualifiés cv extended floating-point types (depuis C++23) ), std::atomic fournit des opérations atomiques supplémentaires appropriées aux types à virgule flottante telles que fetch_add et fetch_sub .

De plus, la spécialisation résultante std::atomic< Floating > a une disposition standard et un destructeur trivial.

Aucune opération ne résulte en un comportement indéfini même si le résultat n'est pas représentable dans le type à virgule flottante. L'environnement floating-point environment en vigueur peut être différent de l'environnement à virgule flottante du thread appelant.

(depuis C++20)

Types membres

Type Définition
value_type T (indépendamment de la spécialisation)
difference_type [1]

value_type (uniquement pour les spécialisations atomic< Integral > et atomic< Floating > (depuis C++20) )

std::ptrdiff_t (uniquement pour les spécialisations std::atomic<U*> )

  1. difference_type n'est pas défini dans le modèle principal std::atomic ou dans les spécialisations partielles pour std::shared_ptr et std::weak_ptr .

Fonctions membres

construit un objet atomique
(fonction membre publique)
stocke une valeur dans un objet atomique
(fonction membre publique)
vérifie si l'objet atomique est sans verrou
(fonction membre publique)
remplace atomiquement la valeur de l'objet atomique par un argument non atomique
(fonction membre publique)
obtient atomiquement la valeur de l'objet atomique
(fonction membre publique)
charge une valeur depuis un objet atomique
(fonction membre publique)
remplace atomiquement la valeur de l'objet atomique et obtient la valeur précédemment détenue
(fonction membre publique)
compare atomiquement la valeur de l'objet atomique avec un argument non atomique et effectue un échange atomique si égal ou un chargement atomique sinon
(fonction membre publique)
(C++20)
bloque le thread jusqu'à notification et changement de la valeur atomique
(fonction membre publique)
(C++20)
notifie au moins un thread en attente sur l'objet atomique
(fonction membre publique)
(C++20)
notifie tous les threads bloqués en attente sur l'objet atomique
(fonction membre publique)

Constantes

[static] (C++17)
indique que le type est toujours sans verrou
(constante membre statique publique)

Fonctions membres spécialisées

Spécialisé pour les types entiers , virgule flottante (depuis C++20) et pointeurs
ajoute atomiquement l'argument à la valeur stockée dans l'objet atomique et obtient la valeur précédemment détenue
(fonction membre publique)
soustrait atomiquement l'argument de la valeur stockée dans l'objet atomique et obtient la valeur précédemment détenue
(fonction membre publique)
ajoute ou soustrait de la valeur atomique
(fonction membre publique)
Spécialisé uniquement pour les types entiers et pointeurs
(C++26)
effectue atomiquement std::max entre l'argument et la valeur de l'objet atomique et obtient la valeur précédemment détenue
(fonction membre publique)
(C++26)
effectue atomiquement std::min entre l'argument et la valeur de l'objet atomique et obtient la valeur précédemment détenue
(fonction membre publique)
incrémente ou décrémente la valeur atomique de un
(fonction membre publique)
Spécialisé uniquement pour les types entiers
effectue atomiquement un ET bit à bit entre l'argument et la valeur de l'objet atomique et obtient la valeur précédemment détenue
(fonction membre publique)
effectue atomiquement un OU bit à bit entre l'argument et la valeur de l'objet atomique et obtient la valeur précédemment détenue
(fonction membre publique)
effectue atomiquement un XOR bit à bit entre l'argument et la valeur de l'objet atomique et obtient la valeur précédemment détenue
(fonction membre publique)
effectue un ET, OU, XOR bit à bit avec la valeur atomique
(fonction membre publique)

Alias de types

Des alias de type sont fournis pour bool et tous les types entiers listés ci-dessus, comme suit :

Alias pour tous les std::atomic<Integral>
atomic_bool
(C++11)
std :: atomic < bool >
(typedef)
atomic_char
(C++11)
std :: atomic < char >
(typedef)
atomic_schar
(C++11)
std :: atomic < signed char >
(typedef)
atomic_uchar
(C++11)
std :: atomic < unsigned char >
(typedef)
atomic_short
(C++11)
std :: atomic < short >
(typedef)
atomic_ushort
(C++11)
std :: atomic < unsigned short >
(typedef)
atomic_int
(C++11)
std :: atomic < int >
(typedef)
atomic_uint
(C++11)
std :: atomic < unsigned int >
(typedef)
atomic_long
(C++11)
std :: atomic < long >
(typedef)
atomic_ulong
(C++11)
std :: atomic < unsigned long >
(typedef)
atomic_llong
(C++11)
std :: atomic < long long >
(typedef)
atomic_ullong
(C++11)
std :: atomic < unsigned long long >
(typedef)
atomic_char8_t
(C++20)
std :: atomic < char8_t >
(typedef)
atomic_char16_t
(C++11)
std :: atomic < char16_t >
(typedef)
atomic_char32_t
(C++11)
std :: atomic < char32_t >
(typedef)
atomic_wchar_t
(C++11)
std :: atomic < wchar_t >
(typedef)
atomic_int8_t
(C++11) (optionnel)
std :: atomic < std:: int8_t >
(typedef)
atomic_uint8_t
(C++11) (optionnel)
std :: atomic < std:: uint8_t >
(typedef)
atomic_int16_t
(C++11) (optionnel)
std :: atomic < std:: int16_t >
(typedef)
atomic_uint16_t
(C++11) (optionnel)
std :: atomic < std:: uint16_t >
(typedef)
atomic_int32_t
(C++11) (optionnel)
std :: atomic < std:: int32_t >
(typedef)
atomic_uint32_t
(C++11) (optionnel)
std :: atomic < std:: uint32_t >
(typedef)
atomic_int64_t
(C++11) (optionnel)
std :: atomic < std:: int64_t >
(typedef)
atomic_uint64_t
(C++11) (optionnel)
std :: atomic < std:: uint64_t >
(typedef)
atomic_int_least8_t
(C++11)
std :: atomic < std:: int_least8_t >
(typedef)
atomic_uint_least8_t
(C++11)
std :: atomic < std:: uint_least8_t >
(typedef)
atomic_int_least16_t
(C++11)
std :: atomic < std:: int_least16_t >
(typedef)
atomic_uint_least16_t
(C++11)
std :: atomic < std:: uint_least16_t >
(typedef)
atomic_int_least32_t
(C++11)
std :: atomic < std:: int_least32_t >
(typedef)
atomic_uint_least32_t
(C++11)
std :: atomic < std:: uint_least32_t >
(typedef)
atomic_int_least64_t
(C++11)
std :: atomic < std:: int_least64_t >
(typedef)
atomic_uint_least64_t
(C++11)
std :: atomic < std:: uint_least64_t >
(typedef)
atomic_int_fast8_t
(C++11)
std :: atomic < std:: int_fast8_t >
(typedef)
atomic_uint_fast8_t
(C++11)
std :: atomic < std:: uint_fast8_t >
(typedef)
atomic_int_fast16_t
(C++11)
std :: atomic < std:: int_fast16_t >
(typedef)
atomic_uint_fast16_t
(C++11)
std :: atomic < std:: uint_fast16_t >
(typedef)
atomic_int_fast32_t
(C++11)
std :: atomic < std:: int_fast32_t >
(typedef)
atomic_uint_fast32_t
(C++11)
std :: atomic < std:: uint_fast32_t >
(typedef)
atomic_int_fast64_t
(C++11)
std :: atomic < std:: int_fast64_t >
(typedef)
atomic_uint_fast64_t
(C++11)
std :: atomic < std:: uint_fast64_t >
(typedef)
atomic_intptr_t
(C++11) (optionnel)
std :: atomic < std:: intptr_t >
(typedef)
atomic_uintptr_t
(C++11) (optionnel)
std :: atomic < std:: uintptr_t >
(typedef)
atomic_size_t
(C++11)
std :: atomic < std:: size_t >
(typedef)
atomic_ptrdiff_t
(C++11)
std :: atomic < std:: ptrdiff_t >
(typedef)
atomic_intmax_t
(C++11)
std :: atomic < std:: intmax_t >
(typedef)
atomic_uintmax_t
(C++11)
std :: atomic < std:: uintmax_t >
(typedef)
Alias pour les types à usage spécifique
atomic_signed_lock_free
(C++20)
un type atomique entier signé sans verrouillage pour lequel l'attente/la notification est la plus efficace
(typedef)
atomic_unsigned_lock_free
(C++20)
un type atomique entier non signé sans verrouillage pour lequel l'attente/la notification est la plus efficace
(typedef)
Note: std::atomic_int N _t , std::atomic_uint N _t , std::atomic_intptr_t , and std::atomic_uintptr_t are defined if and only if std::int N _t , std::uint N _t , std::intptr_t , and std::uintptr_t are defined, respectively.

std::atomic_signed_lock_free et std::atomic_unsigned_lock_free sont optionnels dans les implémentations autonomes.

(depuis C++20)

Notes

Il existe des équivalents de modèles de fonctions non membres pour toutes les fonctions membres de std::atomic . Ces fonctions non membres peuvent être en outre surchargées pour des types qui ne sont pas des spécialisations de std::atomic , mais sont capables de garantir l'atomicité. Le seul type de ce genre dans la bibliothèque standard est std:: shared_ptr < U > .

_Atomic est un mot-clé et est utilisé pour fournir les types atomiques en C.

Il est recommandé que les implémentations garantissent que la représentation de _Atomic(T) en C soit identique à celle de std::atomic<T> en C++ pour tout type T possible. Les mécanismes utilisés pour assurer l'atomicité et l'ordonnancement de la mémoire devraient être compatibles.

Sur GCC et Clang, certaines fonctionnalités décrites ici nécessitent une liaison avec -latomic .

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_lib_atomic_ref 201806L (C++20) std::atomic_ref
__cpp_lib_constexpr_atomic 202411L (C++26) constexpr std::atomic et std::atomic_ref

Exemple

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>
std::atomic_int acnt;
int cnt;
void f()
{
    for (auto n{10000}; n; --n)
    {
        ++acnt;
        ++cnt;
        // Note: for this example, relaxed memory order is sufficient,
        // e.g. acnt.fetch_add(1, std::memory_order_relaxed);
    }
}
int main()
{
    {
        std::vector<std::jthread> pool;
        for (int n = 0; n < 10; ++n)
            pool.emplace_back(f);
    }
    std::cout << "The atomic counter is " << acnt << '\n'
              << "The non-atomic counter is " << cnt << '\n';
}

Sortie possible :

The atomic counter is 100000
The non-atomic counter is 69696

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
LWG 2441 C++11 les typedefs pour les versions atomiques des types entiers
à largeur fixe optionnels manquaient
ajoutés
LWG 3012 C++11 std::atomic<T> était autorisé pour tout T
trivialement copiable mais non copiable
ces spécialisations sont interdites
LWG 3949 C++17 la formulation exigeant que std :: atomic < bool > ait un
destructeur trivial a été accidentellement supprimée en C++17
rétablie
LWG 4069
( P3323R1 )
C++11 le support pour T qualifié cv était discutable interdire que T soit qualifié cv
P0558R1 C++11 la déduction d'arguments template pour certaines
fonctions de types atomiques pouvait échouer
accidentellement ; des opérations de pointeur invalides étaient fournies
la spécification a été substantiellement réécrite :
les typedefs membres value_type
et difference_type sont ajoutés

Voir aussi

le type atomique booléen sans verrouillage
(classe)
pointeur partagé atomique
(spécialisation de modèle de classe)
pointeur faible atomique
(spécialisation de modèle de classe)
Documentation C pour Types atomiques