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
,所以这似乎是唯一的方法(除了其他锁定原语)