3

さまざまなタイプのタスクで PPL "when_all" を使用したいと思います。そして、そのタスクに「then」呼び出しを追加します。

ただし、 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ブロックなので使いたくない)

4

1 に答える 1

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が、それ以外の場合は、タスクのセットをタプルのタスクにバンドルします。

svoidを機能させるには、もう少し手間がかかります。1 つの方法は、forおよびforget_safeを返すa を記述し、返される前に結果のタプルをフィルター処理することです。または、引数をとに分割する a を記述し、それらの 2 つに対して異なる動作をします。どちらもちょっと頭が痛いです。また、タプル追加パターンを実行することもできます (一度に 1 つずつタスクを処理し、 に a を追加するか、に対して何もしないかのいずれかです)。Ttask<T>void_placeholdertask<void>partition_argstask<void>task<T>Ttuplevoid

2 つの C++14 ライブラリ機能 (index_sequence と index_sequence_for) を使用しますが、どちらも C++11 で簡単に記述でき (それぞれ 2 ~ 4 行)、実装も簡単に見つけることができます。

タスクがコピー可能かどうかは忘れましたが、上記のコードにはないと思いました。コピー可能な場合は、上記のコードの短いバージョンが機能します。タイプミスをお詫びします。

于 2015-06-20T22:21:31.640 に答える