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->headheadstd::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 のサンプル コードでのアドレスを取得する必要はない」であることを意味します。しかし、が a を指さなければならず、expected がobjecta を指さなければならないという事実により、コンパイルできるように cppreference でコードを修正する方法を理解するのが難しくなります。リストの先頭をリストの先頭のコピーと比較したいのですが、リストの先頭が型である場合、コピーは型でなければなりません。std::atomic<T>Tstd::atomic<T>*T*std::atomic_compare_exchange_weakstd::atomic<T>*コンパイルすることであり、T*なしでに を割り当てる方法が見つかりませんreinterpret_cast。その場合でも、 の 3 番目のパラメーターstd::atomic_compare_exchange_weakは type である必要がありますTが、cppreference の例では、2 番目と 3 番目のパラメーターの両方が同じ型であることが示されています。これは、cppreference の例が壊れていることを示唆しています。私はそれを修正しようとしましたがreinterpret_cast、単に間違っていると感じる a を使用する必要性に悩まされました。

興味深いことに、このことを理解しようとして、 のmsdn ページstd::atomic_compare_exchange_weakstd::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));
}

未定義の動作に対処したい場合を除き、 はオブジェクトでlist::headある必要があります。std::atomic問題のプラットフォームでは、std::atomicロックを使用して一部またはすべてを実装する必要がある場合があります。したがって、std::atomic<T*>追加のメンバーが含まれる可能性がありreinterpret_cast<std::atomic<T*>*>、UB がプログラムのクラッシュを意味する場合があります。

于 2013-04-24T10:18:37.937 に答える