【问题标题】:Make a safe Reader/Writer vector制作一个安全的读写器向量
【发布时间】:2016-11-28 10:15:26
【问题描述】:

this code 的启发,我正在尝试实现一个读写器vector,它可以安全地通过线程同时调用push_back()

一旦有了这个类,我就可以通过调用std::swap() 创建方法erase(),它交换目标项和最后一项,然后删除集合中的最后一项。这样,我假设性能应该是公平的,因为删除集合中间的项目不会调用移动集合中目标项目之后的所有项目。

不幸的是,下面的代码:

#include <vector>
#include <boost/thread/shared_mutex.hpp> //shared_mutex
#include <memory> //shared_ptr
#include <utility> //swap()

template <class T>
class readers_writer_vector
{
    std::shared_ptr<boost::shared_mutex> pm;
    std::vector<T> data;
public:
    readers_writer_vector() :
        pm(new std::shared_ptr<boost::shared_mutex>){}
    void push_back(const T& item){
        boost::unique_lock<boost::shared_mutex> lock(*pm); //wrong design
        data.push_back(item);
    }
};

int main()
{
    readers_writer_vector<int> db;
    db.push_back(1);
    return 0;
}

产生以下编译错误:

/usr/include/c++/4.9/bits/shared_ptr_base.h:871:39: error: cannot convert ‘std::shared_ptr<boost::shared_mutex>*’ to ‘boost::shared_mutex*’ in initialization
         : _M_ptr(__p), _M_refcount(__p)

// g++ -std=c++11 -Iboost -lboost t.cpp

我该如何解决?请!

编辑:

实现任务远比我想象的复杂。没过多久我就遇到了@Danh 警告过的问题。现在我收到这些错误:

t.cpp:28:8: note: ‘i::i(const i&)’ is implicitly deleted because the default definition would be ill-formed:
 struct i {
        ^
t.cpp:28:8: error: use of deleted function      ‘readers_writer_vector<T>::readers_writer_vector(const readers_writer_vector<T>&) [with T = z]’
t.cpp:13:2: note: declared here 
  readers_writer_vector(readers_writer_vector const&) = delete;

使用这个版本:

template <class T>
class readers_writer_vector
{
    booster::shared_mutex m;
    std::vector<T> data;
public:
    readers_writer_vector() = default;
    readers_writer_vector(readers_writer_vector const&) = delete;
    void push_back(const T& item){
        booster::unique_lock<booster::shared_mutex> lock(m);
        data.push_back(item);
    }
    typename std::vector<T>::reference back(){
        return data.back();
    }
};

struct z {
    int zipcode;
    std::string address;
};

struct i {
    int id;
    readers_writer_vector<z> zipcodes;
};

int main()
{
    readers_writer_vector<i> db;
    db.push_back(i());
    auto &ii=db.back();
    ii.id=1;
    ii.zipcodes.push_back(z());

    auto &zz=ii.zipcodes.back();
    zz.zipcode=11;
    zz.address="aa";

    return 0;
}

除了修复现有错误之外,我还必须为 readers_writer_vector 实现迭代器以使此类有用。

我在考虑要不要继续……

【问题讨论】:

    标签: c++ c++11 std boost-thread


    【解决方案1】:

    因为pmstd::shared_ptr&lt;boost::shared_mutex&gt; 而不是std::shared_ptr&lt;boost::shared_mutex&gt;*。你可以使用这个:

    readers_writer_vector() :
        pm(std::make_shared<boost::shared_mutex>()){}
    

    无论如何,为什么需要指针/智能指针?这个更合适:

    template <class T>
    class readers_writer_vector
    {
        boost::shared_mutex pm;
        std::vector<T> data;
    public:
        void push_back(const T& item){
            boost::unique_lock<boost::shared_mutex> lock(pm);
            data.push_back(item);
        }
    };
    

    【讨论】:

    • 我使用了智能指针,因为我认为将互斥锁直接放入容器中,如std::vector&lt;boost::shared_mutex&gt; v;,不会根据@T.E.D 编译。 An unfortunate implication of this is that a mutex cannot be placed into a container directly. Containers need the ability to safely move their contents around, and you can't do that with a mutex. 和@Adrian Maire 说明的代码。
    • 容器之间的共享互斥锁对我来说没有意义
    • 我不打算在容器之间共享互斥锁。现在我认为 T.E.D.正在谈论与我不同的用例。
    • 当您从其他 readers_writer_vector 复制构造 readers_writer_vector 时,您确实与原始代码共享了互斥锁,我的建议应该禁用复制
    • 我正面临这个矛盾:不能禁用复制构造函数,因为std::vector::push_back() 需要它。
    【解决方案2】:

    你用错误的类型初始化pm;你实际上有

    std::shared_ptr<> pm = new std::shared_ptr<>;
    

    您不能从指向共享指针的指针中分配共享指针。

    替换初始化器
    pm(new boost::shared_mutex)
    

    或直接将互斥体设为成员,而不是使用共享指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-12
      相关资源
      最近更新 更多