标准::螺纹(可拆卸)和异常安全
std::thread (detachable) and exception safety
防护、RAII 和 try/catch 块来确保线程在所有情况下最终都会连接是一种常见的做法。但是,要分离的线程呢?
void aFunction() {
std::thread t {someOtherFunction}; // someOtherFunction may throw!!!
t.detach;
}
我是否应该使用一些异常处理机制来确保即使在异常的情况下也能正确分离t
,或者这并不重要?
std::thread t {someOtherFunction}; // someOtherFunction may throw!!
如果someOtherFunction
可以引发,则需要在该函数中处理异常。如果不是,则默认行为是在异常"转义"线程函数时调用std::terminate
。
std::thread
对象构造和std::thread::detach
本身也可以抛出,因此这些异常需要由aFunction()
处理。
如果线程对象不可联接,则引发 detach()
方法。因此,如果您希望避免处理此异常,则可以添加一个测试,以查看线程是否可连接,然后再尝试分离它。
if (t.joinable())
t.detach;
您被称为detach()
的事实表明您不希望在稍后阶段"加入"(同步)线程,它基本上会自行处理。
与大多数异常处理问题一样,您将如何处理抛出的异常?如果无法处理异常,则要么不捕获它,要么捕获它,记录它并重新抛出它(或调用 std::terminate
)。
如果未连接,~thread 调用 std::terminate 这一事实被认为是标准中的一个缺陷。
Scott Meyers 建议使用ThreadRAII
包装器,如果它仍然可以连接,则在析构函数中加入线程:
class ThreadRAII {
public:
ThreadRAII(std::thread&& thread): t(std::move(thread)) {}
~ThreadRAII() { if (t.joinable()) (t.join(); }
private:
std::thread t;
};
如果someOtherFunction
在另一个线程中引发异常,并且没有人捕获该异常,则调用std::terminate
。
使用 std::current_exception
和 std::rethrow_exception
捕获异常,将其传输到另一个线程并重新抛出它。 例如:
void thread_function(std::exception_ptr* exception)
try {
throw std::runtime_error("test exception");
}
catch(std::exception& e) {
*exception = std::current_exception();
}
int main() {
// Thread creation.
std::exception_ptr other_thread_exception;
std::thread t{thread_function, &other_thread_exception};
// Thread termination.
t.join();
if(other_thread_exception)
std::rethrow_exception(other_thread_exception);
}
我是否应该使用一些异常处理机制来确保即使在异常的情况下也能正确分离
t
,或者这并不重要?
"即使在例外情况下也适当分离"是什么意思?你担心什么样的"不当"分离?
只需立即将其拆下,就不存在异常安全的问题:
std::thread t{something};
t.detach();
如果 t
的构造函数抛出,那么就没有东西可以分离了。如果没有,则将其分离为下一个语句,在此之前没有任何内容可以抛出。
后,它不可联接,因此在离开作用域之前,不需要 RAII 或任何其他机制来确保已联接或分离。
- C++代码中的异常安全
- 编写"anti-lack of memory"异常安全代码
- std:string::substr 异常安全吗?
- 如何以异常安全的方式使用放置新?
- 异常安全服务器
- 实现 std::vector::p ush_back 强异常安全
- 标准::unique_ptr和异常安全
- 如何使用QThreads使无锁生产者-消费者线程交换更加异常安全
- 使功能异常安全
- 与构造函数参数相关的异常安全的习语
- uninitialized_copy() 异常安全吗?
- 为什么我们需要 RAII 来解决异常安全问题
- 异常安全构造函数
- 关于 swap() 操作的异常安全 - 这有什么问题?
- std::vector::擦除异常安全
- 异常安全 - 用于可靠回滚对象状态的模式
- 异常安全的 for 循环
- 异常安全代码和移动语义
- 向量::插入的异常安全保证是什么?
- 异常安全和make_unique