Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用共享ptr实现RCU(读取副本更新)?_C++_Concurrency_Shared Ptr - Fatal编程技术网

C++ 使用共享ptr实现RCU(读取副本更新)?

C++ 使用共享ptr实现RCU(读取副本更新)?,c++,concurrency,shared-ptr,C++,Concurrency,Shared Ptr,我对用户空间RCU(read copy update)非常感兴趣,并试图通过tr1::shared_ptr模拟一个,下面是代码,虽然我是并发编程的新手,但一些专家能帮我复习一下吗 基本思想是,读取器调用get_reading_copy()来获取当前受保护数据的指针(假设它是第一代或G1)。writer调用get_updatening_copy()来获取G1的副本(假设它是G2),并且只允许一个writer进入临界区。更新完成后,writer调用update()进行交换,并使m_data_ptr指

我对用户空间RCU(read copy update)非常感兴趣,并试图通过tr1::shared_ptr模拟一个,下面是代码,虽然我是并发编程的新手,但一些专家能帮我复习一下吗

基本思想是,读取器调用get_reading_copy()来获取当前受保护数据的指针(假设它是第一代或G1)。writer调用get_updatening_copy()来获取G1的副本(假设它是G2),并且只允许一个writer进入临界区。更新完成后,writer调用update()进行交换,并使m_data_ptr指向G2数据。正在进行的读卡器和写卡器现在持有G1的共享_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;
};
模板
类rcu_受保护
{
公众:
T型;
typedef const T const_type;
typedef std::tr1::共享\u ptr rcu\u指针;
typedef std::tr1::共享指针;
受保护的rcu():m_正在写入(0),
m_是_交换(0),
m_数据_ptr(新类型())
{}
rcu常量指针获取读取副本()
{
自旋直到相等(m是交换,0);
返回m_数据\u ptr;
}
rcu\u指针获取\u更新\u副本()
{
自旋直到相等(m是交换,0);
而(!CAS(m_正在写入,0,1))
{/*当超过最大重试次数时,是否休眠以进行回退*/}
rcu_指针新_数据_ptr(新类型(*m_数据_ptr));
//作为spin_,直到_eq没有内存屏障保护,
//我们需要放置一个读屏障来保护数据的加载
//新的\u数据\u ptr在建造前不得重新订购
_ReadBarrier();
返回新的\u数据\u ptr;
}
无效更新(rcu_指针新_数据_ptr)
{
而(!CAS(m_是交换,0,1))
{}
m_数据交换(新数据交换);
//作为spin_,直到_eq没有内存屏障保护,
//我们需要设置一个写屏障来保护
//m_正在写入/m_正在交换在交换前重新订购
_写载体();
m_是_写入=0;
m_是_交换=0;
}
私人:
易变长m_是_书写;
易变长m_正在交换;
rcu_指针m_数据_ptr;
};

乍一看,我会将
自旋~u直到~u eq
调用和相关的自旋锁交换为互斥锁。如果临界区内允许有多个编写器,那么我将使用信号量。这些并发机制的实现可能依赖于操作系统,因此也应该考虑性能因素;通常,它们比忙碌的等待要好

我应该使用rw_互斥来保护阅读和更新,谢谢dvyukov@gmail.com对于审查。。。