std:: atomic_compare_exchange_weak, std:: atomic_compare_exchange_strong, std:: atomic_compare_exchange_weak_explicit, std:: atomic_compare_exchange_strong_explicit
|
Определено в заголовочном файле
<atomic>
|
||
|
template
<
class
T
>
bool
atomic_compare_exchange_weak
|
(1) | (начиная с C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak
|
(2) | (начиная с C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong
|
(3) | (начиная с C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong
|
(4) | (начиная с C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak_explicit
|
(5) | (начиная с C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak_explicit
|
(6) | (начиная с C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong_explicit
|
(7) | (начиная с C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong_explicit
|
(8) | (начиная с C++11) |
Атомарно сравнивает представление объекта (до C++20) представление значения (начиная с C++20) объекта, на который указывает obj , с представлением объекта, на который указывает expected , и если они побитово равны, заменяет первое на desired (выполняет операцию чтения-изменения-записи). В противном случае загружает фактическое значение, на которое указывает obj , в * expected (выполняет операцию загрузки).
| Перегрузки | Модель памяти для | |
|---|---|---|
| операции чтение‑модификация‑запись | операции загрузки | |
| (1-4) | std:: memory_order_seq_cst | std:: memory_order_seq_cst |
| (5-8) | success | failure |
Эти функции определены в терминах функций-членов класса std::atomic :
Если failure сильнее, чем success или (до C++17) является одним из std:: memory_order_release и std:: memory_order_acq_rel , поведение не определено.
Содержание |
Параметры
| obj | - | указатель на атомарный объект для проверки и модификации |
| expected | - | указатель на значение, которое ожидается найти в атомарном объекте |
| desired | - | значение для записи в атомарный объект, если он соответствует ожидаемому |
| success | - | порядок синхронизации памяти для операции чтения-модификации-записи при успешном сравнении |
| failure | - | порядок синхронизации памяти для операции загрузки при неудачном сравнении |
Возвращаемое значение
Результат сравнения: true если * obj был равен * expected , false в противном случае.
Примечания
std::atomic_compare_exchange_weak
и
std::atomic_compare_exchange_weak_explicit
(слабые версии) могут спорадически завершаться неудачей, то есть действовать так, как если бы
*
obj
!
=
*
expected
даже если они равны. При использовании операции сравнения-и-обмена в цикле они обеспечивают лучшую производительность на некоторых платформах.
Когда слабая операция сравнения с обменом потребовала бы цикла, а сильная — нет, предпочтительнее использовать сильную, за исключением случаев, когда объектное представление
T
может включать
биты заполнения,
(до C++20)
биты-ловушки или предоставляет множественные объектные представления для одного значения (например, NaN с плавающей точкой). В этих случаях слабая операция сравнения с обменом обычно работает, поскольку быстро сходится к некоторому стабильному объектному представлению.
Для объединения, у которого некоторые биты участвуют в представлениях значений одних членов, но не других, операции сравнения-и-обмена могут всегда завершаться неудачей, поскольку такие биты заполнения имеют неопределённые значения, когда они не участвуют в представлении значения активного члена.
|
Биты заполнения, которые никогда не участвуют в представлении значения объекта, игнорируются. |
(since C++20) |
Пример
Операции сравнения и обмена часто используются в качестве базовых строительных блоков для lock-free структур данных.
#include <atomic> template<class T> struct node { T data; node* next; node(const T& data) : data(data), next(nullptr) {} }; template<class T> class stack { std::atomic<node<T>*> head; public: void push(const T& data) { node<T>* new_node = new node<T>(data); // put the current value of head into new_node->next new_node->next = head.load(std::memory_order_relaxed); // now make new_node the new head, but if the head // is no longer what's stored in new_node->next // (some other thread must have inserted a node just now) // then put that new head into new_node->next and try again while (!std::atomic_compare_exchange_weak_explicit( &head, &new_node->next, new_node, std::memory_order_release, std::memory_order_relaxed)) ; // the body of the loop is empty // note: the above loop is not thread-safe in at least // GCC prior to 4.8.3 (bug 60272), clang prior to 2014-05-05 (bug 18899) // MSVC prior to 2014-03-17 (bug 819819). See member function version for workaround } }; int main() { stack<int> s; s.push(1); s.push(2); s.push(3); }
Отчёты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| P0558R1 | C++11 |
требовалось точное соответствие типов, потому что
T
выводился из нескольких аргументов
|
T
выводится только
из obj |
Смотрите также
|
атомно сравнивает значение атомарного объекта с неатомарным аргументом и выполняет атомарный обмен при равенстве или атомарную загрузку при неравенстве
(публичная функция-член
std::atomic<T>
)
|
|
|
(C++11)
(C++11)
|
атомно заменяет значение атомарного объекта неатомарным аргументом и возвращает старое значение атомарного объекта
(шаблон функции) |
|
(устарело в C++20)
(удалено в C++26)
|
специализирует атомарные операции для std::shared_ptr
(шаблон функции) |
|
Документация C
для
atomic_compare_exchange
,
atomic_compare_exchange_explicit
|
|