C++11 具有front()和pop()的线程安全队列

C++11 具有front()和pop()的线程安全队列,c++11,thread-safety,C++11,Thread Safety,我已经创建了一个线程安全队列,请参见代码。这个类似乎可以工作,但现在我想让front和pop线程的组合安全,这样线程首先获取元素,然后确定删除相同的元素。我可以想出一些解决方案,但它们对于用户来说并不优雅,否则将失去强大的异常安全保证 第一种解决方案是,用户只需锁定ThreadQueueu,而不是调用front并弹出并解锁ThreadQueue。然而,该类的整体思想是用户不必担心线程安全 第二种解决方案是将队列锁定在重载函数前端内,并仅在pop中解锁它。但是,在这种情况下,用户不允许只呼叫前台或

我已经创建了一个线程安全队列,请参见代码。这个类似乎可以工作,但现在我想让front和pop线程的组合安全,这样线程首先获取元素,然后确定删除相同的元素。我可以想出一些解决方案,但它们对于用户来说并不优雅,否则将失去强大的异常安全保证

第一种解决方案是,用户只需锁定ThreadQueueu,而不是调用front并弹出并解锁ThreadQueue。然而,该类的整体思想是用户不必担心线程安全

第二种解决方案是将队列锁定在重载函数前端内,并仅在pop中解锁它。但是,在这种情况下,用户不允许只呼叫前台或pop,这对用户不友好

我提出的第三个选项是在类frontPop中创建一个公共函数,它返回front元素并删除它。但是在这种情况下,异常安全性消失了

什么是既方便用户又能维护异常安全的解决方案

class ThreadQueue: private std::queue<std::string>
{
  mutable std::mutex d_mutex;

  public:
    void pop()
    {
      lock_guard<mutex> lock(d_mutex);
      pop();
    }

    std::string &front()
    {
      lock_guard<mutex> lock(d_mutex);
      return front();
    }

    // All other functions

  private:

};

通常的解决方案是提供一个组合的front&pop,它接受一个用于存储弹出值的引用,并在弹出值时返回一个为true的bool:

bool pop(std::string& t) {
  lock_guard<mutex> lock(d_mutex);

  if (std::queue<std::string>::empty()) {
    return false;
  }

  t = std::move(std::queue<std::string>::front());
  std::queue<std::string>::pop();
  return true;
}

移动分配引发的任何异常都会在修改队列之前发生,从而保持值类型的移动分配运算符提供的异常保证。

通常的解决方案是提供一个组合的前端&pop,该前端&pop接受用于存储弹出值的引用,如果弹出一个值,则返回一个布尔值:

bool pop(std::string& t) {
  lock_guard<mutex> lock(d_mutex);

  if (std::queue<std::string>::empty()) {
    return false;
  }

  t = std::move(std::queue<std::string>::front());
  std::queue<std::string>::pop();
  return true;
}

移动分配引发的任何异常都会在修改队列之前发生,从而保持值类型的移动分配运算符提供的异常保证。

使函数原子化\u front\u和\u pop…为什么frontPop会使异常安全消失?如果前端调用在内部成功,而pop调用失败,队列将保持不变。前端和pop在std::队列中分开的原因是相同的,对吗?使函数原子化\u front\u和\u pop…为什么frontPop会使异常安全消失?如果前端调用在内部成功,而pop调用失败,那么队列将保持不变。前端和pop在std::队列中被分离,原因相同,对吗?