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
( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,
typename std::atomic<T>::value_type desired ) noexcept;
| (1) | (с C++11) |
template< class T >
bool atomic_compare_exchange_weak
( volatile std::atomic<T>* obj,
typename std::atomic<T>::value_type* expected,
typename std::atomic<T>::value_type desired ) noexcept;
| (2) | (с C++11) |
template< class T >
bool atomic_compare_exchange_strong
( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,
typename std::atomic<T>::value_type desired ) noexcept;
| (3) | (с C++11) |
template< class T >
bool atomic_compare_exchange_strong
( volatile std::atomic<T>* obj,
typename std::atomic<T>::value_type* expected,
typename std::atomic<T>::value_type desired ) noexcept;
| (4) | (с C++11) |
template< class T >
bool atomic_compare_exchange_weak_explicit
( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,
typename std::atomic<T>::value_type desired,
std::memory_order success, std::memory_order failure ) noexcept;
| (5) | (с C++11) |
template< class T >
bool atomic_compare_exchange_weak_explicit
( volatile std::atomic<T>* obj,
typename std::atomic<T>::value_type* expected,
typename std::atomic<T>::value_type desired,
std::memory_order success, std::memory_order failure ) noexcept;
| (6) | (с C++11) |
template< class T >
bool atomic_compare_exchange_strong_explicit
( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected,
typename std::atomic<T>::value_type desired,
std::memory_order success, std::memory_order failure ) noexcept;
| (7) | (с C++11) |
template< class T >
bool atomic_compare_exchange_strong_explicit
( volatile std::atomic<T>* obj,
typename std::atomic<T>::value_type* expected,
typename std::atomic<T>::value_type desired,
std::memory_order success, std::memory_order failure ) noexcept;
| (8) | (с C++11) |
Атомарно сравнивает представление объекта(до C++20)представление значения(с C++20) объекта, на который указывает obj с представлением объекта, на который указывает expected, и, если они битово-равны, заменяет первое на desired (выполняет операцию read-modify-write). В противном случае загружает фактическое значение, на которое указывает obj в *expected (выполняет операцию загрузки).
| Перегрузки | Модель памяти для | |
|---|---|---|
| операции read‑modify‑write | операции загрузки | |
| (1-4) |
std::memory_order_seq_cst | std::memory_order_seq_cst |
| (5-8) |
success |
failure |
Эти функции определяются через члены функции std::atomic.
obj->compare_exchange_weak(*expected, desired)
obj->compare_exchange_strong(*expected, desired)
obj->compare_exchange_weak(*expected, desired, success, failure)
obj->compare_exchange_strong(*expected, desired, success, failure)
Если failure сильнее, чем success или(до C++17) является одним из std::memory_order_release и std::memory_order_acq_rel, поведение является неопределённым.
Параметры
| obj | - | указатель на атомарный объект для проверки и изменения |
| expected | - | указатель на значение, ожидаемое в атомарном объекте |
| desired | - | значение, которое необходимо сохранить в атомарном объекте, если оно ожидаемое |
| success | - | порядок синхронизации памяти для операции read-modify-write, если сравнение прошло успешно |
| failure | - | порядок синхронизации памяти для операции загрузки, если сравнение не прошло успешно |
Возвращаемое значение
Результат сравнения: true если *obj было равно *expected, false в противном случае.
Примечания
std::atomic_compare_exchange_weak и std::atomic_compare_exchange_weak_explicit (слабые версии) могут случайно терпяться неудачу, то есть действовать так, как если бы *obj != *expected , даже если они равны. Когда сравнение-и-обмен находится в цикле, они будут обеспечивать лучшую производительность на некоторых платформах.
Когда слабое сравнение-и-обмен потребовало бы цикла, а сильное - нет, сильное предпочтительнее, если представление объекта T может включать биты заполнения,(до C++20) биты ловушки или предлагает несколько представлений объекта для одного значения (например, плавающей точки NaN). В этих случаях слабое сравнение-и-обмен, как правило, работает, потому что быстро сходится к некоторому стабильному представлению объекта.
Для объединения с битами, которые участвуют в представлении значений некоторых членов, но не других, сравнение-и-обмен может всегда терпяться неудачей, потому что такие биты заполнения имеют неопределённые значения, когда они не участвуют в представлении значения активного члена.
| Биты заполнения, которые никогда не участвуют в представлении значения объекта, игнорируются. | (с C++20) |
Пример
Операции сравнения-и-обмена часто используются в качестве основных строительных блоков для атомарных структур данных.
#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 | Применимо к | Поведение, опубликованное | Правильное поведение |
|---|---|---|---|
| P0558R1 | C++11 | требовалось точное совпадение типов, потому чтоT был выведен из нескольких аргументов |
T выводится толькоиз obj |
См. также
| атомарно сравнивает значение атомарного объекта с неатомарным аргументом и выполняет атомарный обмен, если они равны, или атомарную загрузку, если нет (общедоступный член-функция std::atomic<T>) |
|
|
(C++11)(C++11) | атомарно заменяет значение атомарного объекта неатомарным аргументом и возвращает старое значение атомарного (шаблон функции) |
|
(устарело в C++20) | специализирует атомарные операции для std::shared_ptr (шаблон функции) |
C документация для atomic_compare_exchange, atomic_compare_exchange_explicit |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/atomic/atomic_compare_exchange