アップグレード/ダウングレード

upgrade_to_writer メソッドを使用して、リーダーロックをライターロックにアップグレードできます。次に例を示します。

std::vector<string> MyVector;
typedef spin_rw_mutex MyVectorMutexType;
MyVectorMutexType MyVectorMutex;
 
void AddKeyIfMissing( const string& key ) {
    // MyVectorMutex のリーダーロックを取得
    MyVectorMutexType::scoped_lock lock(MyVectorMutex,/*is_writer=*/false);
    size_t n = MyVector.size();
    for( size_t i=0; i<n; ++i )
        if( MyVector[i]==key ) return;
    if( !lock.upgrade_to_writer() )
        // ロックが一時的に解放されている間にキーが追加されたか確認
        for( int i=n; i<MyVector.size(); ++i )
           if(MyVector[i]==key ) return; 
    vector.push_back(key);
}

ベクトルは、再度検索する必要があることに注意してください。これは、upgrade_to_writer が、アップグレードの前に一時的にロックを解放しなければならない可能性があるためです。この処理を行わないと、「ロックの問題」の説明にあるように、デッドロックが発生することがあります。upgrade_to_writer メソッドは bool を返します。ロックを解放しなくてもロックのアップグレードが成功した場合は true で、一時的にロックが解放された場合は false です。このため、upgrade_to_writer で false が返された場合、コードは別のライターによってキーが挿入されていないかをチェックするため、再検索を実行します。この例では、キーが常にベクトルの最後に追加され、削除されないことが想定されています。このような想定により、ベクトル全体の検索をやり直す必要はなく、最初に検索された範囲以外の要素のみを検索できます。重要な点は、upgrade_to_writer が false を返したとき、リーダーロックを保持している間に確立されたすべての想定は無効になり、再確認が必要になることです。

アップグレードに対し、downgrade_to_reader というメソッドがありますが、実際に使用するケースはあまりないでしょう。

関連情報