2017-08-21 8 views
0

私は、独立した未来が終わるのを待つために、実行時間に関して最適な方法を探しています。C++ 11で複数の先物を待つ最適な方法は何ですか?

auto f1 = async(launch::async, []{ doSomething(’.’); }); 
auto f2 = async(launch::async, []{ doSomething(’+’); }); 

while (f1.wait_for(chrono::seconds(0)) != future_status::ready && f2.wait_for(chrono::seconds(0)) != future_status::ready) 
{ }; 

f1.get(); 
f2.get(); 

こう先物の少なくとも一方が終了すると、その後のため.get()を呼び出している間、私たちはループを残して次のように2つしか先物への対処

シンプルで、一つは最適な方法を持つことができますどちらもプログラムが時間を失わせることはありません。

n先物はいかがですか?

+0

私はあなたが 'while()'ループの中で意味のある作業が行われていることを暗示していると思います。さもなければ、これは私にとって意味をなさないでしょう。 – Frank

+0

はい、ループ内にthis_thread :: yield();を入れることができます。 –

+0

しかし、 'get()'が返るのを待っている間、あなたのスレッドを中断してCPUを解放させることよりも、何も積極的に何もしていませんか? – Frank

答えて

0

std :: futureの任意の数を作成したい場合は、それらをすべてstd :: vectorに入れるのに役立ちます。その後、ベクトルをループして結果をgetにすることができます。 getが処理を待機していることに注意してください。

//Result type defined here: http://en.cppreference.com/w/cpp/thread/async 
template<typename F, typename... Args> 
using AsyncResult = std::result_of_t<std::decay_t<F>(std::decay_t<Args>...)>; 

template<typename T, typename F1, typename F2> 
void do_par(const std::vector<T>& ts, F1&& on_t, F2&& accumulate) { 
    //The standard doesn't require that these futures correspond to individual 
    //threads, but there's a good chance they'll be implemented that way. 
    std::vector<std::future<AsyncResult<F1, T>>> threads; 
    for (const T& t : ts) { threads.push_back(std::async(on_t, t)); } 

    //Think of this as just waiting on each thread to finish. 
    for (auto& future : threads) { accumulate(std::move(future)); } 
} 

template<typename T, typename F> 
std::vector<AsyncResult<F, T>> map_par(const std::vector<T>& ts, F&& on_t) { 
    std::vector<AsyncResult<F, T>> out; 
    do_par(ts, on_t, [&](auto&& future_){ out.push_back(future_.get()); }); 
    return out; 
} 

std::string doSomething(const std::string&){ return std::string("yo"); } 

そして、あなたはこの単純なmap_par機能は非常に頭のきれるソリューションではありません

const std::vector<std::string> results = map_par(
    std::vector<std::string>{".", "+", "et al"}, doSomething 
); 

を行うことができます。個々のスレッドを生成するオーバーヘッドを削減するスレッドキュー(スレッドプールを所有するスレッドキュー)を設定すると、CPUコアよりスレッドが多い場合に発生するコンテキスト切り替えのオーバーヘッドが助長される可能性があります。あなたのスレッドキューインプリメンテーションは、std :: asyncに似た独自のasyncメソッドを持つことができます。

入力順序に関係なく、結果がすぐに使用されるようにするには、シングル・リーダー・マルチプル・ライター(それに付随してキューを含む)を設定することを検討してください。

std :: condition_variableは、上記の両方の提案に役立ちます。

関連する問題