<mutex>和<condition_variable>的异常处理

时间:2016-05-13 08:51:23

标签: c++ multithreading c++11 mutex condition-variable

假设

  1. 没有发生未定义的行为,
  2. 没有发生死锁,
  3. 通过正确的线程以正确的顺序锁定和解锁互斥锁正确的次数,
  4. 非递归互斥锁未多次锁定,
  5. 锁定递归互斥锁不会超过maximum level of ownership
  6. 没有谓词传递给条件变量throw和
  7. 标准库提供的时钟,时间点和持续时间与std::互斥和条件变量一起使用
  8. 是否可以保证对不同类型的std::互斥锁和条件变量(除了构造它们)的操作不会抛出任何异常(尤其是std::system_error类型的异常)?

    例如,在以下方法的情况下:

    void MyClass::setVariable() {
        std::lock_guard<std::mutex> const guard(m_mutex);
        m_var = 42; // m_var is of type int
        m_conditionVariable.notify_all();
    }
    
    void MyClass::waitVariable() {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_conditionVariable.wait(lock, [this]() noexcept { return m_var == 42; });
    }
    

    假设noexcept是否安全,或者应该在调用者周围编写一些try-catch块?或者有任何警告吗?

    请在C ++ 11,C ++ 14及更高版本中考虑所有类型的互斥锁和条件变量。

2 个答案:

答案 0 :(得分:9)

简答:不(抱歉)

如果底层同步对象无法执行其操作,则任何这些操作都将抛出std::system_error

这是因为同步原语的正确操作取决于:

  1. 可用的系统资源。

  2. 程序的其他部分没有使原语无效

  3. 虽然公平地说,如果(1)正在发生,可能是时候重新设计应用程序或在负载较少的机器上运行它。

    如果(2)发生,程序在逻辑上不一致。

    话虽如此,

      

    或者应该在callites周围写一些try-catch块?

    也没有。

    您应该在以下条件下编写try / catch块:

    1. 程序可以对错误情况做一些有用的事情(例如修复它或询问用户是否要再试一次)

    2. 您希望向错误添加一些信息并重新抛出它以提供诊断性痕迹痕迹(例如,嵌套异常)

    3. 您希望记录失败并继续。

    4. 否则,c ++异常处理的重点是允许RAII处理资源重新获取并允许异常流出调用堆栈,直到找到想要处理它的处理程序。

      创建面包屑跟踪的示例:

      void wait_for_object()
      try
      {
          _x.wait();  // let's say it throws a system_error on a loaded system
      }
      catch(...)
      {
        std::throw_with_nested(std::runtime_error(__func__));
      }
      

答案 1 :(得分:2)

感谢link T.C.现在提供我会说是 - 您的代码应该是安全的。由于将来标准device_or_resource_busy将被删除,并且该问题的作者说这种情况不能以任何合理的方式发生,那么lock只有两种可能性:

  

(13.1) - operation_not_permitted - 如果线程没有   特权执行操作。

     

(13.2) - resource_deadlock_would_occur - 如果实现检测到   会发生僵局。

这两种情况都被你的前提条件排除在外。所以你的代码应该安全使用noexcept。