C++ PPL什么时候有不同类型的任务?
我想在不同类型的任务上使用PPL“when_all”。并为该任务添加一个“then”调用 但是当_all返回一个接受向量的任务时,所有元素都必须是相同的类型。那我该怎么做呢 这是我想到的,但感觉有点像黑客:C++ PPL什么时候有不同类型的任务?,c++,tbb,ppl,C++,Tbb,Ppl,我想在不同类型的任务上使用PPL“when_all”。并为该任务添加一个“then”调用 但是当_all返回一个接受向量的任务时,所有元素都必须是相同的类型。那我该怎么做呢 这是我想到的,但感觉有点像黑客: //3 different types: int out1; float out2; char out3; //Unfortunately I cant use tasks with return values as the types would be different ... au
//3 different types:
int out1;
float out2;
char out3;
//Unfortunately I cant use tasks with return values as the types would be different ...
auto t1 = concurrency::create_task([&out1](){out1 = 1; }); //some expensive operation
auto t2 = concurrency::create_task([&out2](){out2 = 2; }); //some expensive operation
auto t3 = concurrency::create_task([&out3](){out3 = 3; }); //some expensive operation
auto t4 = (t1 && t2 && t3); //when_all doesnt block
auto t5 = t4.then([&out1, &out2, &out3](){
std::string ret = "out1: " + std::to_string(out1) + ", out2: " + std::to_string(out2) + ", out3: " + std::to_string(out3);
return ret;
});
auto str = t5.get();
std::cout << str << std::endl;
//3种不同类型:
int out1;
浮出水面2;
charout3;
//不幸的是,我不能使用返回值的任务,因为类型不同。。。
autot1=concurrency::create_任务([&out1](){out1=1;})//一些昂贵的手术
autot2=并发::创建_任务([&out2](){out2=2;})//一些昂贵的手术
自动t3=并发::创建_任务([&out3](){out3=3;})//一些昂贵的手术
自动t4=(t1和t2和t3)//当你都不阻塞的时候
自动t5=t4。然后([&out1,&out2,&out3](){
std::string ret=“out1:”+std::to_string(out1)+”,out2:“+std::to_string(out2)+”,out3:”+std::to_string(out3);
返回ret;
});
auto str=t5.get();
任务组将工作
否则:
template<class...Ts>
struct get_many{
std::tuple<task<Ts>...> tasks;
template<class T0, size_t...Is>
std::tuple<T0,Ts...>
operator()(
std::task<T0> t0,
std::index_sequence<Is...>
){
return std::make_tuple(
t0.get(),
std::get<Is>(tasks).get()...
);
}
template<class T0>
std::tuple<T0,Ts...>
operator()(task<T0> t0){
return (*this)(
std::move(t0),
std::index_sequence_for<Ts...>{}
);
}
};
template<class T0, class...Ts>
task<std::tuple<T0,Ts...>> when_every(
task<T0> next, task<Ts>... later
){
return next.then( get_many<Ts...>{
std::make_tuple(std::move(later)...)
} );
}
模板
结构得到很多{
std::元组任务;
模板
std::tuple
运算符()(
std::任务t0,
std::index_序列
){
返回std::make_tuple(
t0.get(),
std::get(任务).get()。。。
);
}
模板
std::tuple
运算符()(任务t0){
返回(*本页)(
标准::移动(t0),
{}的索引序列
);
}
};
模板
每周一次任务(
任务下一步,任务…稍后
){
下一个返回。然后(获取多个){
std::make_tuple(std::move(稍后)…)
} );
}
它不适用于void
任务,而是将任何一组任务捆绑到一个元组任务中
让void
s发挥作用需要做更多的工作。一种方法是编写一个get_safe
,为task
返回T
,为task
返回void\u占位符,然后在返回前过滤结果元组。或者编写一个partition_args
,将args拆分为task
和task
,并对这两个arg执行不同的操作。两者都有点令人头痛。我们还可以做一个元组附加模式(我们一次处理一个任务,可以将T
附加到元组
,或者对void
不做任何事情)
它使用了两个C++14库功能(index_sequence和index_sequence_for),但都很容易用C++11编写(每行2-4行),实现也很容易找到
我忘记了如果任务是可复制的,我假设它不在上面的代码中。如果是可复制的,则可以使用上述代码的较短版本。对于任何打字错误,我深表歉意。谢谢。元组而不是向量构成了一个很好的接口。我可能错了,但我的印象是我应该避免打电话给get(或等待)。因为它们阻止并扼杀了可伸缩性。因此,在我看来,实现一个称为“get”的定制“when_all”是错误的。查看concurrency::when_all的实现,看起来只有在所有任务完成后才调用“get”,所以它不会阻塞。但我在这方面做得太深了。最后,我不确定如何以非阻塞的方式将任务连续链接在一起。@有人只在then
中调用get
,而then
代码是异步运行的(我假设它返回一个任务
),希望是在第一个任务的线程中。酷,我的错。谢谢