読者です 読者をやめる 読者になる 読者になる

C++0x Shared_ptr atomic access

C++

shared_ptr のスレッド安全性レベルは、標準ライブラリのデフォルトレベルなので
const 操作は複数スレッドで同時に行うことができますが、更新には排他アクセスを必要とします。


しかし、より強い保証を必要とする場合がいくつかあります。


atomic な shared_ptr、つまり2つのスレッドによる同期なしの並列な更新に耐えることが可能な shared_ptr がほしいという強い要求があります(Boost MLなどで)
よくある動機は、生のポインタへの atomic な操作と、ガベージコレクションを合わせたパターンを移植したいというものです。


このケースに対応するため、 に以下の関数が追加されます

template <class T>
bool atomic_is_lock_free( shared_ptr<T> const * p );

template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p );
template<class T> shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order mo );

template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r );
template<class T> void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order mo );

template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r );
template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order mo );

template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w );
template<class T> bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, memory_order success, memory_order failure );

ちなみに、これは Boost 1.36 ですでに実装されています。

# なんで shared_ptr のポインタなんだろ。



以下は、典型的な "lock-free" reader/writerパターンの例

shared_ptr<State> ps;


void reader()
{
    shared_ptr<State const> p = atomic_load(&ps);
    // *p を使った処理...
}

// 単一writer
void writer()
{
    shared_ptr<State> p(new State(*ps));
    // *p を更新する...
    atomic_store(&ps, move(p));
}

// 複数writer
void writer()
{
    shared_ptr<State> p = atomic_load(&ps);

    do
    {
        shared_ptr<State> q(new State(*p));
        // *p を更新する...
    }
    while(!atomic_compare_exchange(&ps, &p, move(q)));
}


N2674 Shared_ptr atomic access, revision 1

C++0x言語拡張まとめ