Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.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::exception\u ptr线程安全吗?_C++_Exception_Concurrency_Thread Safety_Race Condition - Fatal编程技术网

C++ std::exception\u ptr线程安全吗?

C++ std::exception\u ptr线程安全吗?,c++,exception,concurrency,thread-safety,race-condition,C++,Exception,Concurrency,Thread Safety,Race Condition,我有一个通过std::thread不断运行、创建和管理的工作线程。在工作线程的顶层,我有一个try/catch块,其中有一个while循环。如果异常泄漏到线程的顶层,我将捕获它并将其存储在std::exception_ptr中,该类也是非静态线程函数的成员: // In class header (inside class declaration) std::exception_ptr m_threadException; // In class CPP file void MyClass::

我有一个通过
std::thread
不断运行、创建和管理的工作线程。在工作线程的顶层,我有一个try/catch块,其中有一个while循环。如果异常泄漏到线程的顶层,我将捕获它并将其存储在
std::exception_ptr
中,该类也是非静态线程函数的成员:

// In class header (inside class declaration)
std::exception_ptr m_threadException;

// In class CPP file
void MyClass::MyThreadFunction()
{
    try {
        while (true) {
            // Do thread stuff
        }
    }
    catch (std::exception const& e) {
        m_threadException = std::current_exception();
    }
}
一旦线程由于这种异常而死亡,我的类(也主要由主线程使用)还不知道它。我的计划是在类的所有主要函数的开头添加线程检查点,如下所示:

void MyClass::SomethingMainThreadCalls()
{
    if (m_threadException) {
        std::rethrow_exception(m_threadException);
        m_threadException = nullptr; // Somehow reset it back to null; not sure if this will work
    }

    // Do normal function stuff
}
假设这是一个好主意,那么在我的主线程检查异常是否为null(调用
SomethingMainThreadCalls()
时)和工作线程分配给它之间可能存在争用条件。我还没有找到任何关于这是否本质上是线程安全的(由标准保证)或者在这种情况下我是否负责线程同步的信息(还没有检查C++11草案)

如果是后者,那么使用
std::atomic
来保持它的简单性是一个好主意吗?例如:

std::atomic<std::exception_ptr> m_threadException;
std::原子m_线程异常;

像这样的?希望我的问题的答案也包括一些关于最佳实践的好建议和信息。提前感谢。

该标准没有指定什么是
std::exception\u ptr
的实现,因此
std::exception\u ptr
的线程安全性也未指定


只要在异常指针上加上一些锁,代码就可以了

标准中没有关于其螺纹安全的特殊声明。因此,它提供了默认的标准保证:可以访问单独的实例,但不能访问相同的实例

我建议改为使用
原子
(如果没有其他原因,
异常
不可复制,因此不能放入
原子
)让其他代码知道已设置了
异常
。只要:

  • 在设置标志之前,请先设置
    m_threadException
  • 检查标志后,您将读取
    m_threadException
  • 您可以使用适当的加载/存储内存顺序来设置/检查标志。默认设置很好
  • 您只需编写
    m_threadException
    一次

  • 刚刚尝试过这样做,但是
    std::atomic
    需要一个简单的可复制类型,
    std::exception\u ptr
    不需要。您应该像我一样得到编译错误(当使用MSVC VS2019、C++14时)。

    这是一个好主意。它还消除了将异常设置为空的需要。根据cppreference.com,对于
    exception\u ptr
    ,没有文档化的接口,所以我甚至不确定它是否有
    nullptr
    @void.pointer的赋值运算符:它确实有一个“文档化的接口”。它说:“
    std::exception\u ptr
    满足的要求。”它甚至说默认构造函数和复制构造函数做什么。还有比较运算符。对不起,隧道视觉。我希望在该页面上有一个实际的接口规范,就像cppreference.com通常对其他类类型所做的那样。谢谢。是的,我甚至不能实例化一个
    std::atomic
    ,所以这似乎是唯一的方法(除了其他锁定原语)