Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ PPL什么时候有不同类型的任务?_C++_Tbb_Ppl - Fatal编程技术网

C++ PPL什么时候有不同类型的任务?

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

我想在不同类型的任务上使用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 ...
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
代码是异步运行的(我假设它返回一个
任务
),希望是在第一个任务的线程中。酷,我的错。谢谢