20

<atomic>侵入共有ポインターを作成しており、参照カウンターにC++ 11 機能を使用しています。私のコードの関連する断片は次のとおりです。

//...
mutable std::atomic<unsigned> count;
//...

void
SharedObject::addReference() const
{
    std::atomic_fetch_add_explicit (&count, 1u,
        std::memory_order_consume);
}

void
SharedObject::removeReference() const
{
    bool destroy;

    destroy = std::atomic_fetch_sub_explicit (&count, 1u,
        std::memory_order_consume) == 1;

    if (destroy)
        delete this;
}

memory_order_acquire最初はandから始めましたが、それで十分だとmemory_order_release確信しました。memory_order_consumeさらに検討した結果、memory_order_relaxedうまくいくはずだと私には思えます。

ここで問題はmemory_order_consume、操作に使用できるかどうか、または弱い順序付け ( memory_order_relaxed) を使用できるかどうか、またはより厳密な順序付けを使用する必要があるかどうかです。

4

1 に答える 1

22
void
SharedObject::addReference() const
{
    std::atomic_fetch_add_explicit (&count, 1u, std::memory_order_relaxed);
}

void
SharedObject::removeReference() const
{
    if ( std::atomic_fetch_sub_explicit (&count, 1u, std::memory_order_release) == 1 ) {
         std::atomic_thread_fence(boost::memory_order_acquire);
         delete this;
    }
}

が厳密に の後にあるatomic_thread_fenceように使用したい。参照deletefetch_sub

リンクされたテキストからの引用:

参照カウンターの増加は、常に memory_order_relaxed を使用して行うことができます。オブジェクトへの新しい参照は、既存の参照からのみ形成できます。また、あるスレッドから別のスレッドに既存の参照を渡すには、必要な同期が既に提供されている必要があります。

別のスレッドでオブジェクトを削除する前に、(既存の参照を介して) 1 つのスレッドでオブジェクトへの可能なアクセスを強制することが重要です。これは、参照をドロップした後の「解放」操作 (この参照を介したオブジェクトへのアクセスは明らかに以前に行われている必要があります) と、オブジェクトを削除する前の「取得」操作によって実現されます。

fetch_sub 操作に memory_order_acq_rel を使用することは可能ですが、これにより、参照カウンターがまだゼロに達していない場合に不要な「取得」操作が発生し、パフォーマンスが低下する可能性があります。

于 2012-04-22T15:26:57.760 に答える