在http://en.cppreference.com/w/cpp/atomic/atomic_compare_exchange上,以下示例代码作为示例使用std::atomic_compare_exchange_weak:
void append(list* s, node* n)
{
node* head;
do {
head = s->head;
n->next = head;
} while(! std::atomic_compare_exchange_weak(s->head, head, n));
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,这已经比较的效果*(s->head)有head,当我所相信的希望是比较s->head用head.std::atomic_compare_exchange_weak在这个例子中&(s->head),第一个参数应该是,还是我错过了什么?
更新:规格std::atomic_compare_exchange_weak说:
bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired) noexcept;
bool atomic_compare_exchange_weak(A* object, C * expected, C desired) noexcept;
Run Code Online (Sandbox Code Playgroud)
效果:原子地,比较对象指向的内存的内容...与预期中的内容相等...
我认为这意味着*object与之相比较expected,但进一步的研究表明,实际意义是*object与之比较*expected(即,"在expected"中的意思是"指向expected").这意味着我原来问题的答案是"不,没有必要s->head在cppreference中获取示例代码中的地址".但object必须指向a std::atomic<T>和预期必须指向a 的事实T使我很难弄清楚如何在cppreference处更正代码以便编译.我们想要将列表的头部与列表头部的副本进行比较,但如果列表的头部是类型std::atomic<T>*,则T*如果调用的话,副本必须是类型的std::atomic_compare_exchange_weak是编译,我找不到一种方法来指定std::atomic<T>*一个T*没有a reinterpret_cast.即使这样,第三个参数std::atomic_compare_exchange_weak也需要是类型T,但cppreference中的示例显示第二个和第三个参数属于同一类型.这告诉我,cppreference的例子被打破了.我试图修复它,但是我被使用了一个reinterpret_cast只是感觉不对的需要而感到困扰.
有趣的是,在我试图弄清楚这些东西时,我检查了msdn页面std::atomic_compare_exchange_weak,我很惊讶地看到该页面显示了原型std::atomic_compare_exchange_*strong*!
有人可以发布用于std::atomic_compare_exchange_weak在单链表的前面插入节点的合理代码吗?没有必要担心ABA问题或做任何花哨的事情.我只想看到编译的骨架代码.
小智 2
一个正确的例子是:
struct list {
std::atomic<node*> head;
};
...
void append(list* s, node* n)
{
node* head;
do {
head = s->head;
n->next = head;
} while (!std::atomic_compare_exchange_weak(&(s->head), &head, n));
// or while (!s->head.compare_exchange_weak(head, n));
}
Run Code Online (Sandbox Code Playgroud)
除非您想处理未定义的行为,否则需要list::head是一个对象。std::atomic相关平台可能需要std::atomic使用锁来实现部分或全部功能。因此,std::atomic<T*>可能会包含其他成员,并且reinterpret_cast<std::atomic<T*>*>UB 意味着您的程序崩溃。