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 起) |
原子地比较由 obj 指向的对象的 对象表示 (C++20 前) 值表示 (C++20 起) 与由 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 | - | 比较失败时加载操作的内存同步顺序 |
返回值
比较结果:当 * obj 等于 * expected 时返回 true ,否则返回 false 。
注释
std::atomic_compare_exchange_weak
和
std::atomic_compare_exchange_weak_explicit
(弱版本)允许出现伪失败,即即使
*
obj
!
=
*
expected
实际相等时也可能操作失败。当在循环中进行比较交换操作时,这些弱版本在某些平台上能提供更佳性能。
当弱比较并交换需要循环而强比较并交换不需要时,除非
T
的对象表示可能包含
填充位、
(直至 C++20)
陷阱位,或为同一值提供多种对象表示(例如浮点数 NaN),否则应优先选用强比较并交换。在这些情况下,弱比较并交换通常更适用,因为它能快速收敛到某个稳定的对象表示。
对于联合体中某些成员参与值表示而其他成员不参与的位,比较并交换操作可能总是失败,因为当这些填充位不参与当前活跃成员的值表示时,它们具有不确定的值。
|
从不参与对象值表示的填充位将被忽略。 |
(since 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)
|
原子地以非原子参数替换原子对象的值并返回原子的旧值
(函数模板) |
|
为 std::shared_ptr 特化的原子操作
(函数模板) |
|
|
C 文档
关于
atomic_compare_exchange
,
atomic_compare_exchange_explicit
|
|