std::exception_ptr 线程安全吗?
Is std::exception_ptr thread safe?
我有一个不断 运行 的工作线程,通过 std::thread
创建和管理。在我的工作线程的顶层,我有一个 try/catch 块,里面有一个 while 循环。如果异常泄漏到线程的顶层,我会捕获它并将其存储在 std::exception_ptr
中,它是 class 的成员,该 class 也拥有非静态线程函数:
// 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();
}
}
一旦线程因为这种异常而死掉,我的class(也是主要被主线程使用的)还不知道。我的计划是将线程检查点添加到所有 class 的主要函数的开头,如下所示:
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
}
假设这是个好主意,在我的主线程检查 exception_ptr 是否为空(调用 SomethingMainThreadCalls()
时)和工作线程分配给它。我还没有找到任何信息(还没有检查 C++11 草案)关于这是否本质上是线程安全的(由标准保证)或者在这种情况下我是否负责线程同步。
如果是后者,使用 std::atomic
是保持简单的好主意吗?示例:
std::atomic<std::exception_ptr> m_threadException;
类似的东西?希望我的问题的答案也包括一些好的建议和关于此处最佳实践的信息。提前致谢。
标准没有规定std::exception_ptr
的实现是什么,所以std::exception_ptr
的线程安全性也没有规定。
只要用一些锁包裹异常指针,代码就可以了。
exception_ptr
在标准中对其线程安全性没有特别说明。因此,它提供了默认的标准保证:访问单独的实例是可以的,访问 相同的实例 则不行。
我建议改用 atomic<bool>
(如果没有其他原因,exception_ptr
不可简单复制,因此不能放在 atomic<T>
中)让其他代码知道 exception_ptr
已设置。只要:
- 你设置了
m_threadException
before setting the flag
- 您阅读
m_threadException
后检查标志
- 你使用适当的load/store内存命令来set/check标志。默认值很好
- 您只写
m_threadException
一次。
刚刚尝试这样做,但是 std::atomic
需要一个普通的可复制类型,std::exception_ptr
不是。你应该像我一样得到编译错误(当使用 MSVC VS2019,C++14 时)。
我有一个不断 运行 的工作线程,通过 std::thread
创建和管理。在我的工作线程的顶层,我有一个 try/catch 块,里面有一个 while 循环。如果异常泄漏到线程的顶层,我会捕获它并将其存储在 std::exception_ptr
中,它是 class 的成员,该 class 也拥有非静态线程函数:
// 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();
}
}
一旦线程因为这种异常而死掉,我的class(也是主要被主线程使用的)还不知道。我的计划是将线程检查点添加到所有 class 的主要函数的开头,如下所示:
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
}
假设这是个好主意,在我的主线程检查 exception_ptr 是否为空(调用 SomethingMainThreadCalls()
时)和工作线程分配给它。我还没有找到任何信息(还没有检查 C++11 草案)关于这是否本质上是线程安全的(由标准保证)或者在这种情况下我是否负责线程同步。
如果是后者,使用 std::atomic
是保持简单的好主意吗?示例:
std::atomic<std::exception_ptr> m_threadException;
类似的东西?希望我的问题的答案也包括一些好的建议和关于此处最佳实践的信息。提前致谢。
标准没有规定std::exception_ptr
的实现是什么,所以std::exception_ptr
的线程安全性也没有规定。
只要用一些锁包裹异常指针,代码就可以了。
exception_ptr
在标准中对其线程安全性没有特别说明。因此,它提供了默认的标准保证:访问单独的实例是可以的,访问 相同的实例 则不行。
我建议改用 atomic<bool>
(如果没有其他原因,exception_ptr
不可简单复制,因此不能放在 atomic<T>
中)让其他代码知道 exception_ptr
已设置。只要:
- 你设置了
m_threadException
before setting the flag - 您阅读
m_threadException
后检查标志 - 你使用适当的load/store内存命令来set/check标志。默认值很好
- 您只写
m_threadException
一次。
刚刚尝试这样做,但是 std::atomic
需要一个普通的可复制类型,std::exception_ptr
不是。你应该像我一样得到编译错误(当使用 MSVC VS2019,C++14 时)。