2016-04-11 7 views
1

私は現在、いくつかの時間のかかるタスクをシーケンシャルな方法で実行する同期C++コードをいくつか持っています。私はBoostコルーチンを使ってこれを並列タスクにリファクタリングすることを検討しています。コルーチンの実行の間にスリープを実施

タスクのコアは、同期API(現在使用している)または非同期API(定期的にポーリングしてアクションを実行し、完了したかどうかを判断する)を提供する外部ライブラリの呼び出しです。 。 APIはスレッドセーフではありませんが、非同期バージョンを使用すると、ポーリングAPI自体が同時に呼び出されない限り、同時に発生する複数のリクエストに対処できます。

(私はスレッドをシフトしたくないので、ASIOラッパーなどを使用するのではなく、コルーチンAPIを直接使用する必要があるようですが、そうでない場合は説得力があります。現在のところ1.55となっているので、ファイバーライブラリは利用できませんが、この使用法では過剰使用のように見えます)。

現時点ではコルーチンとの私の主な質問は、ポーリングにスロットリングを実装する方法がわかりません - 私は並行して実行する100のタスクがあると言います。私はそれが100のすべてのタスクを通して1つのポーリングを実行し、指定された時間スレッドをスリープさせたい。タスクの中には他のタスクより早く完了するものもあるので、後でループごとに40個のタスクをポーリングしてから、同じ時間をスリープすることがあります。私はそれが介入する睡眠なしに連続して2回同じ仕事を投票することを望んでいません。

+1

あなたの説明をコーディングするのを止めるのは何ですか?コルーチンをコーディングして眠りたい場合にのみコードを生成してから、すべてのアクティブなコルーチンを実行し、スリープして繰り返します。おそらくまったく馴染みがないでしょう。 –

+0

たぶん、これは私が想定していたより簡単です。 – Miral

答えて

0

私が思ったよりもはるかに簡単です。これは私がこれまでになってしまったものです:

typedef boost::coroutines::coroutine<void>::push_type coroutine; 
typedef boost::coroutines::coroutine<void>::pull_type yield_context; 
typedef std::vector<coroutine> coroutine_list; 

bool run_once_all(coroutine_list& coros) 
{ 
    bool pending = false; 
    for (auto& coro : coros) 
    { 
     if (coro) 
     { 
      coro(); 
      pending = pending || !coro.empty(); 
     } 
    } 
    return pending; 
} 

void run_all(coroutine_list& coros, 
      const boost::chrono::nanoseconds& idle_ns) 
{ 
    while (run_once_all(coros)) 
    { 
     boost::this_thread::sleep_for(idle_ns); 
    } 
} 

void run_all(coroutine_list& coros, yield_context& yield) 
{ 
    while (run_once_all(coros)) 
    { 
     yield(); 
    } 
} 

アイデアは、署名void (yield_context&)run_allで、その後emplace_backラムダ関数、あなたがcoroutine_listを作るということです。最初のものはトップレベルのもので、2番目のものはネストされたコルーチンのものです。

私はそれに大きな運動をまだ与えていませんが、動作するようです。実際には少し驚いたようなものはすでに図書館にはありません。

関連する問題