私は侵入共有ポインタを作成していますが、参照カウンタとしてC++ 11 <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
とmemory_order_release
最初に開始しているが、その後、私はmemory_order_consume
が十分であることを自分自身を確信させました。さらなる審議の末、memory_order_relaxed
でも動作するはずです。
問題は、操作にmemory_order_consume
を使用することができますか、弱い発注(memory_order_relaxed
)を使用することができますか、より厳密な発注を使用する必要がありますか?
カウンタは基本的に 'delete'文の再帰的ロックとして機能するので、' removeReference'の 'addReference'と' releaseReference'の 'acquire'は正しい順序です。しかし、あなたの 'addReference'は、カウンタがゼロでないことを確認しなければなりません! –
@KerrekSB:オブジェクトは、 'SharedPtr <>'に代入される前にオブジェクトが最初に作成された後、 'addReference()'でカウンタがゼロになります。取得/解放のセマンティクスは、常に有効であるようです。しかし、より弱い順序制約を使用することはできませんし、なぜそうではありませんか? – wilx
ゼロについて:refcountが1であると仮定します。スレッド1はオブジェクトを削除したいので、減算を呼び出します。この時点でスレッド2がスレッド数を増やしたい場合、0に1をインクリメントしますが、スレッド1は先に進み、とにかくオブジェクトを削除します。それは避けるべきです。 –