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 (выполняет операцию чтения-модификации-записи). В противном случае загружает фактическое значение, на которое указывает obj, в *expected (выполняет операцию загрузки).
| Перегрузки | Модель памяти для | |
|---|---|---|
| операции чтения-модификации-записи | операции загрузки | |
| (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 | - | порядок синхронизации памяти для операции чтения-модификации-записи при успешном сравнении |
| failure | - | порядок синхронизации памяти для операции загрузки при неудачном сравнении |
Возвращаемое значение
Результат сравнения: true, если *obj было равно *expected, и false в противном случае.
Примечания
Операциям std::atomic_compare_exchange_weak и std::atomic_compare_exchange_weak_explicit (слабым версиям) разрешено завершаться ложной неудачей, то есть вести себя так, как если бы *obj != *expected, даже если значения равны. При использовании compare-and-exchange в цикле они могут обеспечивать более высокую производительность на некоторых платформах.
Если для слабой операции compare-and-exchange потребуется цикл, а для сильной — нет, предпочтительна сильная операция, если только представление объекта T не может включать биты заполнения,(до C++20) биты-ловушки или несколько представлений объекта для одного и того же значения (например, NaN с плавающей точкой). В таких случаях слабая операция compare-and-exchange обычно работает, поскольку быстро сходится к некоторому устойчивому представлению объекта.
Для объединения, в котором биты участвуют в представлении значения одних членов, но не других, операция compare-and-exchange может всегда завершаться неудачей, поскольку такие биты заполнения имеют неопределённые значения, когда они не участвуют в представлении значения активного члена.
| Биты заполнения, которые никогда не участвуют в представлении значения объекта, игнорируются. | (начиная с 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)(удалено в C++26) | специализирует атомарные операции для 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/cpp/atomic/atomic_compare_exchange