8

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->head比较headstd::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;

效果:以原子方式比较对象指向的内存内容...与预期的相等...

我认为这意味着与*object进行比较expected,但进一步的研究表明,实际含义是*object与进行比较*expected(即,“in expected”表示“指向expected”)。这意味着我最初问题的答案是“不,没有必要s->head在 cppreference 的示例代码中获取地址”。但是object必须指向 astd::atomic<T>并且预期必须指向 a的事实T使我很难弄清楚如何更正 cppreference 处的代码以便编译。我们想将列表的头部与列表头部的副本进行比较,但是如果列表的头部是 type std::atomic<T>*,那么T*如果调用std::atomic_compare_exchange_weak是编译,我找不到将 a 分配std::atomic<T>*T*没有 a 的方法reinterpret_cast。即使这样,第三个参数 tostd::atomic_compare_exchange_weak也需要是 type T,但是 cppreference 的示例显示第二个和第三个参数是相同的类型。这向我表明 cppreference 的示例已损坏。我试图修复它,但我被需要使用一个reinterpret_cast感觉不对的东西所阻碍。

有趣的是,在我试图弄清楚这些东西的过程中,我查看了msdn 页面std::atomic_compare_exchange_weak,我很沮丧地看到该页面显示了std::atomic_compare_exchange_*strong*

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

4

1 回答 1

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

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

于 2013-04-24T10:18:37.937 回答