2010-05-12 5 views
4

Меня очень интересует RCU (чтение-копирование-обновление) в пространстве пользователя и попытка имитировать один через tr1 :: shared_ptr, вот код, в то время как я действительно новичок в параллельном программировании, эксперты помогают мне пересмотреть?Использование shared_ptr для реализации RCU (чтение-копирование-обновление)?

Основная идея заключается в том, что читатель вызывает get_reading_copy(), чтобы получить указатель на текущие защищенные данные (скажем, это поколение один или G1). писатель вызывает get_updating_copy(), чтобы получить копию G1 (скажем, это G2), и только один писатель может войти в критический раздел. После того, как обновление выполнено, автор вызывает update(), чтобы выполнить обмен, и сделайте m_data_ptr, указывающий на данные G2. Текущие читатели и писатель теперь держат shared_ptr (s) G1, и либо читатель, либо автор в конечном итоге освободят данные 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; 
}; 
+0

Я должен использовать rw_mutex для защиты чтения и обновления, благодаря [email protected] для просмотра ... – yongsun

ответ

1

С первого взгляда я бы обменивать spin_until_eq вызовы и связанные с ними спин-блокировки, для взаимной блокировки. Если в критической секции было разрешено более одного писателя, я бы использовал семафор. Эти реализации механизма параллелизма могут быть зависимыми от ОС, поэтому должны учитываться соображения производительности; обычно они лучше, чем заняты.