在cppreference中atomic_compare_exchange_weak的示例代码是否正确?

时间:2013-04-16 00:18:16

标签: c++ c++11

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));
}

我的理解是,这具有将*(s->head)head进行比较的效果,当我认为需要将s->headhead进行比较时。本例中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;
  

效果:原子地,比较内存的内容   对象指向...与预期中的平等......

我认为这意味着*objectexpected进行了比较,但进一步的研究表明实际意义是*object*expected进行比较(即, “in expected”表示“expected指出”。这意味着我原来问题的答案是“不,没有必要在cppreference的示例代码中获取s->head的地址”。但object必须指向std::atomic<T>且预期必须指向T的事实使我很难弄清楚如何在cppreference处更正代码以便编译。我们希望将列表的头部与列表头部的副本进行比较,但如果列表的头部类型为std::atomic<T>*,则副本必须为T*类型,如果致电std::atomic_compare_exchange_weak是为了编译,我找不到在没有std::atomic<T>*的情况下将T*分配给reinterpret_cast的方法。即使这样,std::atomic_compare_exchange_weak的第三个参数也需要是T类型,但cppreference中的示例显示第二个和第三个参数属于同一类型。这告诉我,cppreference的例子被打破了。我试图修复它,但是因为需要使用感觉不对的reinterpret_cast而受到阻碍。

有趣的是,在我尝试解决这些问题时,我检查了msdn page for std::atomic_compare_exchange_weak,我很惊讶地看到该页面显示了std::atomic_compare_exchange_*strong*的原型!

有人发布使用std::atomic_compare_exchange_weak在单链表前插入节点的合理代码吗?没有必要担心ABA问题或做任何花哨的事情。我只想看到编译的骨架代码。

1 个答案:

答案 0 :(得分: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));
}

list::head需要是std::atomic对象,除非您想要处理未定义的行为。有问题的平台可能需要使用锁来实现部分或全部std::atomic内容。因此,std::atomic<T*>可能包含其他成员,而reinterpret_cast<std::atomic<T*>*>就是UB意味着您的程序崩溃的情况。