Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.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++ std::无序映射上的线程安全包装器_C++_Multithreading_C++11_Unordered Map - Fatal编程技术网

C++ std::无序映射上的线程安全包装器

C++ std::无序映射上的线程安全包装器,c++,multithreading,c++11,unordered-map,C++,Multithreading,C++11,Unordered Map,我试图在std::unordered\u映射之上实现一个线程安全的包装器类 具有以下开始和结束功能是否安全 std::unordered_map<Key, T, Hash, Pred, Alloc> umap; iterator begin() { return umap.begin(); } iterator end() { return umap.end();

我试图在std::unordered\u映射之上实现一个线程安全的包装器类 具有以下开始和结束功能是否安全

        std::unordered_map<Key, T, Hash, Pred, Alloc> umap;
        iterator begin() {
            return umap.begin();
        }   
        iterator end() {
            return umap.end();
        }
std::无序映射umap;
迭代器begin(){
返回umap.begin();
}   
迭代器结束(){
返回umap.end();
}
另外,如果复制/移动运算符=执行中存在任何明显错误,请予以评论

    concurrent_unordered_map& operator=(const concurrent_unordered_map& other) ;
    {
        if (this!=&other) {
          std::lock(entry_mutex, other.entry_mutex);
          std::lock_guard<boost::shared_mutex> _mylock(entry_mutex, std::adopt_lock);
          std::shared_lock<boost::shared_mutex> _otherlock(other.entry_mutex, std::adopt_lock);
          umap = other.umap;
        }
        return *this;           
    }
    concurrent_unordered_map& operator=(concurrent_unordered_map&& other) 
    {
        if (this!=&other) {
          std::lock(entry_mutex, other.entry_mutex);
          std::lock_guard<boost::shared_mutex> _mylock(entry_mutex, std::adopt_lock);
          std::shared_lock<boost::shared_mutex> _otherlock(other.entry_mutex, std::adopt_lock);
          umap = std::move(other.umap)
        }
        return *this;       
    }
concurrent\u unordered\u映射和运算符=(const concurrent\u unordered\u映射和其他);
{
如果(此!=&其他){
std::lock(entry\u mutex,other.entry\u mutex);
std::lock\u guard\u mylock(入口互斥,std::采用锁);
std::shared_lock _otherlock(other.entry_mutex,std::adoption_lock);
umap=other.umap;
}
归还*这个;
}
并发无序映射和运算符=(并发无序映射和其他)
{
如果(此!=&其他){
std::lock(entry\u mutex,other.entry\u mutex);
std::lock\u guard\u mylock(入口互斥,std::采用锁);
std::shared_lock _otherlock(other.entry_mutex,std::adoption_lock);
umap=std::move(other.umap)
}
归还*这个;
}
谢谢
MJV

即使同步每个方法调用,也无法创建提供与底层标准容器相同接口的线程安全容器。这是因为接口规范本身并不打算在多线程环境中使用

下面是一个示例:假设您有多个线程同时插入到同一个容器对象:

c->insert(new_value);
因为您同步了每个方法调用,所以它工作得很好,这里没有问题

但同时,另一个线程尝试循环容器中的所有元素:

auto itr = c->begin();
while (itr != c->end())
{
    // do something with itr
    ++itr;
}
我这样写是为了把问题弄清楚:即使对begin和end的调用在内部是同步的,也不能以原子方式执行“遍历所有元素”的操作,因为要完成此任务,需要不止一个方法调用。当循环运行时,任何其他线程向容器中插入内容时,此场景就会中断

因此,如果您想拥有一个无需外部同步即可使用的容器,则需要一个线程安全接口。例如,“通过所有元素循环”任务可以通过为每个方法提供一个For_以原子方式完成:

c.for_each([](const value_type& value)
{
    // do something with value
}); 

即使同步每个方法调用,也无法创建提供与基础标准容器相同接口的线程安全容器。这是因为接口规范本身并不打算在多线程环境中使用

下面是一个示例:假设您有多个线程同时插入到同一个容器对象:

c->insert(new_value);
因为您同步了每个方法调用,所以它工作得很好,这里没有问题

但同时,另一个线程尝试循环容器中的所有元素:

auto itr = c->begin();
while (itr != c->end())
{
    // do something with itr
    ++itr;
}
我这样写是为了把问题弄清楚:即使对begin和end的调用在内部是同步的,也不能以原子方式执行“遍历所有元素”的操作,因为要完成此任务,需要不止一个方法调用。当循环运行时,任何其他线程向容器中插入内容时,此场景就会中断

因此,如果您想拥有一个无需外部同步即可使用的容器,则需要一个线程安全接口。例如,“通过所有元素循环”任务可以通过为每个方法提供一个For_以原子方式完成:

c.for_each([](const value_type& value)
{
    // do something with value
}); 

您不能简单地同步每个方法并获取线程安全对象,因为某些操作需要多个方法调用,如果容器在方法调用之间发生变化,则会中断

一个典型的例子是迭代

实现线程安全的一个简单方法是滥用C++14的以下功能:

template<class T>
struct synchronized {
  // one could argue that rvalue ref qualified version should not be
  // synchronized...  but I think that is wrong
  template<class F>
  std::result_of_t< F(T const&) > read( F&& f ) const {
    auto&& lock = read_lock();
    return std::forward<F>(f)(t);
  }
  template<class F>
  std::result_of_t< F(T&) > write( F&& f ) {
    auto&& lock = write_lock();
    return std::forward<F>(f)(t);
  }
  // common operations, useful rvalue/lvalue overloads:
  // get a copy of the internal guts:
  T copy() const& { return read([&](auto&&t)->T{return t;}); }
  T copy() && { return move(); }
  T move() { return std::move(*this).write([&](auto&&t)->T{return std::move(t);}); }
private:
  mutable std::shared_timed_mutex mutex;
  std::shared_lock<std::shared_timed_mutex> read_lock() const {
    return std::shared_lock<std::shared_timed_mutex>(mutex);
  }
  std::unique_lock<std::shared_timed_mutex> write_lock() {
    return std::unique_lock<std::shared_timed_mutex>(mutex);
  }
  T t;
public:
  // relatively uninteresting boilerplate
  // ctor:
  template<class...Args>
  explicit synchronized( Args&&... args ):
    t(std::forward<Args>(args)...)
  {}
  // copy ctors: (forwarding constructor above means need all 4 overloads)
  synchronized( synchronized const& o ) :t(std::forward<decltype(o)>(o).copy()) {}
  synchronized( synchronized const&& o ):t(std::forward<decltype(o)>(o).copy()) {}
  synchronized( synchronized & o )      :t(std::forward<decltype(o)>(o).copy()) {}
  synchronized( synchronized && o )     :t(std::forward<decltype(o)>(o).copy()) {}
  // copy-from-T ctors: (forwarding constructor above means need all 4 overloads)
  synchronized( T const& o ) :t(std::forward<decltype(o)>(o)) {}
  synchronized( T const&& o ):t(std::forward<decltype(o)>(o)) {}
  synchronized( T & o )      :t(std::forward<decltype(o)>(o)) {}
  synchronized( T && o )     :t(std::forward<decltype(o)>(o)) {}
};
模板
结构同步{
//有人可能会争辩说,不应该使用右值ref限定版本
//同步…但我认为这是错误的
模板
std::读取(F&&F)常数的结果{
auto&&lock=read_lock();
返回标准::向前(f)(t);
}
模板
std::twrite(F&&F)的结果{
auto&&lock=write_lock();
返回标准::向前(f)(t);
}
//常见操作、有用的右值/左值重载:
//获取内部内脏的副本:
T copy()const&{return read([&](auto&&T)->T{return T;});}
T copy()&&{return move();}
T move(){return std::move(*this).write([&](auto&&T)->T{return std::move(T);});}
私人:
可变std::共享\u定时\u互斥互斥;
std::shared_lock read_lock()常量{
返回std::共享_锁(互斥锁);
}
std::unique_lock write_lock(){
返回std::唯一锁(互斥锁);
}
T;
公众:
//相对乏味的样板
//执行官:
模板
显式同步(Args&&…Args):

t(std::forward

您不能简单地同步每个方法并获取线程安全对象,因为某些操作需要多个方法调用,如果容器在方法调用之间发生变异,则会中断

一个典型的例子是迭代

实现线程安全的一个简单方法是滥用C++14的以下功能:

template<class T>
struct synchronized {
  // one could argue that rvalue ref qualified version should not be
  // synchronized...  but I think that is wrong
  template<class F>
  std::result_of_t< F(T const&) > read( F&& f ) const {
    auto&& lock = read_lock();
    return std::forward<F>(f)(t);
  }
  template<class F>
  std::result_of_t< F(T&) > write( F&& f ) {
    auto&& lock = write_lock();
    return std::forward<F>(f)(t);
  }
  // common operations, useful rvalue/lvalue overloads:
  // get a copy of the internal guts:
  T copy() const& { return read([&](auto&&t)->T{return t;}); }
  T copy() && { return move(); }
  T move() { return std::move(*this).write([&](auto&&t)->T{return std::move(t);}); }
private:
  mutable std::shared_timed_mutex mutex;
  std::shared_lock<std::shared_timed_mutex> read_lock() const {
    return std::shared_lock<std::shared_timed_mutex>(mutex);
  }
  std::unique_lock<std::shared_timed_mutex> write_lock() {
    return std::unique_lock<std::shared_timed_mutex>(mutex);
  }
  T t;
public:
  // relatively uninteresting boilerplate
  // ctor:
  template<class...Args>
  explicit synchronized( Args&&... args ):
    t(std::forward<Args>(args)...)
  {}
  // copy ctors: (forwarding constructor above means need all 4 overloads)
  synchronized( synchronized const& o ) :t(std::forward<decltype(o)>(o).copy()) {}
  synchronized( synchronized const&& o ):t(std::forward<decltype(o)>(o).copy()) {}
  synchronized( synchronized & o )      :t(std::forward<decltype(o)>(o).copy()) {}
  synchronized( synchronized && o )     :t(std::forward<decltype(o)>(o).copy()) {}
  // copy-from-T ctors: (forwarding constructor above means need all 4 overloads)
  synchronized( T const& o ) :t(std::forward<decltype(o)>(o)) {}
  synchronized( T const&& o ):t(std::forward<decltype(o)>(o)) {}
  synchronized( T & o )      :t(std::forward<decltype(o)>(o)) {}
  synchronized( T && o )     :t(std::forward<decltype(o)>(o)) {}
};
模板
结构同步{
//有人可能会争辩说,不应该使用右值ref限定版本
//同步…但我认为这是错误的
模板
std::读取(F&&F)常数的结果{
auto&&lock=read_lock();
返回标准::向前(f)(t);
}
模板
std::twrite(F&&F)的结果{
auto&&lock=write_lock();
返回标准::向前(f)(t);
}
//常见操作、有用的右值/左值重载:
//获取内部内脏的副本:
T copy()const&{return read([&](auto&&T)->T{return T;});}
T copy()&&{return move();}
T move(){return std::move(*this).write([&](auto&&T)->T{return std::m