4

私はユーザー空間の RCU (read-copy-update) に非常に興味があり、tr1::shared_ptr を介してシミュレートしようとしています。コードは次のとおりです。私は並行プログラミングの初心者ですが、何人かの専門家が助けてくれますか?私がレビューしますか?

基本的な考え方は、リーダーが get_reading_copy() を呼び出して、現在保護されているデータ (第 1 世代または G1 としましょう) のポインターを取得することです。ライターは get_updating_copy() を呼び出して G1 (G2 としましょう) のコピーを取得し、クリティカル セクションに入ることができるライターは 1 つだけです。更新が完了した後、ライターは update() を呼び出してスワップを実行し、m_data_ptr が G2 データを指すようにします。現在進行中のリーダーとライターは G1 の shared_ptr を保持しており、最終的にリーダーまたはライターのいずれかが G1 データの割り当てを解除します。

新しいリーダーはすべて G2 へのポインターを取得し、新しいライターは G2 のコピーを取得します (G3 としましょう)。G1 はまだリリースされていない可能性があるため、複数世代のデータが共存している可能性があります。

template <typename T>
class rcu_protected
{
public:
    typedef T                                   type;
    typedef const T                             const_type;
    typedef std::tr1::shared_ptr<type>          rcu_pointer;
    typedef std::tr1::shared_ptr<const_type>    rcu_const_pointer;

    rcu_protected() : m_is_writing(0),
                      m_is_swapping(0),
                      m_data_ptr (new type())
    {}

    rcu_const_pointer get_reading_copy ()
    {
        spin_until_eq (m_is_swapping, 0);

        return m_data_ptr;
    }

    rcu_pointer get_updating_copy ()
    {
        spin_until_eq (m_is_swapping, 0);

        while (!CAS (m_is_writing, 0, 1))
        {/* do sleep for back-off when exceeding maximum retry times */}

        rcu_pointer new_data_ptr(new type(*m_data_ptr));

        // as spin_until_eq does not have memory barrier protection,
        // we need to place a read barrier to protect the loading of
        // new_data_ptr not to be re-ordered before its construction
        _ReadBarrier();

        return new_data_ptr;
    }

    void update (rcu_pointer new_data_ptr)
    {
        while (!CAS (m_is_swapping, 0, 1))
        {}

        m_data_ptr.swap (new_data_ptr);

        // as spin_until_eq does not have memory barrier protection,
        // we need to place a write barrier to protect the assignments of
        // m_is_writing/m_is_swapping be re-ordered bofore the swapping
        _WriteBarrier();

        m_is_writing = 0;
        m_is_swapping = 0;
    }

private:
    volatile long m_is_writing;
    volatile long m_is_swapping;
    rcu_pointer m_data_ptr;
};
4

1 に答える 1

1

一見すると、spin_until_eqコールと関連するスピンロックをミューテックスと交換します。クリティカルセクション内で複数のライターが許可された場合は、セマフォを使用します。これらの同時実行メカニズムの実装はOSに依存する可能性があるため、パフォーマンスの考慮事項も考慮する必要があります。通常、彼らは忙しい待機よりも優れています。

于 2010-11-17T17:38:22.323 に答える