std::thread
类本质上是异常不安全的,因为它的析构函数调用 std::terminate
。
std::thread t( function );
// do some work
// (might throw!)
t.join();
当然,您可以将构造和 join()
之间的所有内容放在 try-catch block 中,但如果您知道要加入或分离,这可能会变得乏味且容易出错不管发生什么。
所以我在想如何围绕它编写最简单的包装器,但同时也支持其他假设类型的线程。例如,boost::thread
或完全不同的东西,只要它有 joinable()
、join()
和 detach ()
方法。这是我的进展情况:
// handles threads safely
// Acts the same as the underlying thread type, except during destruction.
// If joinable, will call join (and block!) during destruction.
// Keep in mind that any exception handling will get delayed because of that;
// it needs to wait for the thread to finish its work first.
template <class UNDERLYING_THREAD = std::thread>
class scoped_thread: public UNDERLYING_THREAD
{
public:
typedef UNDERLYING_THREAD thread_type;
using thread_type::thread_type;
scoped_thread()
: thread_type() {}
scoped_thread( scoped_thread && other )
: thread_type( std::move( other ) ) {}
scoped_thread & operator = ( scoped_thread && other )
{
thread_type & ref = *this;
ref = std::move( other );
return *this;
}
~scoped_thread()
{
if( thread_type::joinable() )
thread_type::join();
}
};
// handles autonomous threads safely
// Acts the same as the underlying thread type, except during destruction.
// If joinable, will call detach during destruction.
// Make sure it doesn't use any scoped resources since the thread can remain
// running after they go out of scope!
template <class UNDERLYING_THREAD = std::thread>
class free_thread
{
// same except it calls detach();
}
这似乎可行,但我想知道是否有办法避免手动定义构造函数和移动赋值运算符。我注意到的最大问题可能是,如果您提供一个带有删除的移动构造函数的类作为模板参数,编译将失败。
对于如何避免这种情况,您有什么建议吗?或者这种方法还有其他更大的问题吗?
最佳答案
如果你想对异步任务进行适当的异常处理,也许你应该使用 std::future
而不是 std::thread
。您可以在未来使用 get()
而不是使用 join()
,如果 future 抛出异常,则 get()
将导致相同的异常。
一个简单的例子:
#include <future>
#include <iostream>
int my_future_task(int my_arg) {
throw std::runtime_error("BAD STUFF!");
return my_arg;
}
int main(int argc, char* argv[]) {
auto my_future = std::async(my_future_task, 42);
try {
my_future.get();
}
catch(std::exception &e) {
std::cout << "Caught exception: " << e.what() << std::endl;
}
return 0;
}
另见:
关于c++ - 使 std::thread 异常安全的最简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33307099/