想象我创建一个像这样的线程:
std::jthread t( []( std::string &&str ) {}, std::move( str ) );
如果线程创建失败怎么办?字符串是否保证保留其旧内容?
实际上,
std::thread
调用的参数存储在类似于std::tuple
按值的形式中。这必须在创建 std::thread
的上下文中完成。然后在线程中以类似于std::apply
的方式调用函数对象。
不会指定何时发生创建实际线程原语失败的情况。它可能发生在用于将参数编组到新的
std::tuple
的 std::thread
创建之前,也可能发生在创建之后。
粗略的伪代码:
std::thread bob( func, arg1, arg2 );
是
std::thread ctor( F&& func, A1&&, arg1, A2&&, arg2 ) {
// the data the thread needs to run:
using package_t = std::tuple<std::decay_t<F>, std::decay_t<A1>, std::decay_t<A2>>;
// bundle it up and put it on the heap:
auto* ptmp = new package_t( std::forward<F>(func), std::forward<A1>(arg1), std::forward<A2>(arg2) );
// use lower level primitives to interact with OS threading:
m_pthread_handle = pthread_create(
// Lower level function pointer:
[](void* p){
// unbundle the package of data and run the function on the arguments:
auto* ptmp = static_cast<package*>(p);
std::get<0>(*ptmp)( std::get<1>(std::move(*ptmp)), std::get<2>(std::move(*ptmp)) );
// clean up
delete ptmp;
},
ptmp
);
}
错误检查/异常处理和许多其他细节被跳过。
但是,重要的是,参数包“ptmp”是在我们可能在线程创建失败之前创建的,这一事实并未指定。