4
我對用戶空間RCU非常感興趣,並試圖通過tr1 :: shared_ptr模擬一個,這裏是代碼,而我真的是併發編程的新手,會有一些專家幫我審查?使用shared_ptr實現RCU(讀取副本更新)?
基本思想是,閱讀器調用get_reading_copy()來獲取當前受保護數據的指針(假設它是第一代或G1)。編寫者調用get_updating_copy()來獲得G1的副本(假設它是G2),並且只有一個編寫者被允許進入關鍵部分。更新完成後,編寫器調用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;
};
我應該使用rw_mutex來保護閱讀和更新,謝謝[email protected]的審查... – yongsun 2010-06-08 08:31:20