PPL when_all与不同类型的任务?

时间:2015-06-20 20:20:31

标签: c++ tbb ppl

我想在不同类型的任务上使用PPL“when_all”。并为该任务添加“然后”调用。

但是when_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;

任何人都有更好的主意吗?

(parallel_invoke阻止所以我不想使用它)

1 个答案:

答案 0 :(得分:1)

任务组将有效。

失败:

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)...)
  } );
}

不适用于void个任务,但除此之外将任何一组任务捆绑到一个元组任务中。

void工作更加有效。一种方法是编写get_safe,为T返回task<T>,为void_placeholder返回task<void>,然后在返回之前过滤生成的元组。或者写一个partition_args,将args拆分为task<void>task<T>,并对其中的两个采取不同的行动。两者都有点头疼。我们还可以执行元组附加模式(我们一次一个地处理任务,并且可以T附加tuple或者void不执行任何操作)。

它使用两个C ++ 14库特性(index_sequence和index_sequence_for),但两者都很容易用C ++ 11编写(每行2-4行),并且很容易找到实现。

我忘了如果任务是可复制的,我认为它不在上面的代码中。如果它是可复制的,则上述代码的较短版本将起作用。为任何错别字道歉。