2014-01-07 12 views
12

私はいくつかのjavascriptを書いてきましたが、私が環境について気に入っているいくつかの事の1つは、非同期イベントのハンドラを作るための約束/未来を使う方法です。C++の未来/ javascriptの約束?

C++では未来の結果が利用可能になるまでブロックする必要がありますが、Javascriptでは.then(fn)を書くことができ、結果が準備ができたら関数を呼び出します。これは、後で呼び出し元と同じスレッドでこれを行うため、スレッド同期に関する問題はありません。少なくともC++と同じではありません。

私はC++思っているようなもの -

auto fut = asyncImageLoader("cat.jpg"); 
fut.then([](Image img) { std::cout << "Image is now loaded\n" << image; }); 

は、cでこれを達成する方法はあります++?明らかに、コールバックのディスパッチを処理するには、何らかのイベントキューとイベントループが必要です。私はたぶん最終的にこのコードを書くことができましたが、標準的な機能を使って簡単に目的を達成する方法があるかどうかを見たいと思っていました。

+1

重複していませんが、密接に関連しています:http://stackoverflow.com/questions/14489935/implementing-futurethen-equivalent-for-asynchronous-execution-in-c11 –

+0

とにかく重複していませんが、 )何らかの理由で私の検索でそれが見つからなかった。 – jcoder

+1

"これは[javascript]が同じスレッドでこれを行うことが重要です"。通常、2つのスレッドが関係します。 (i)遅延が生成され、非同期ハンドラが添付されたスレッド、(ii)遅延が満たされた、または拒否されたスレッド、および非同期ハンドラが実行されるスレッド。 (a)ハンドラは、遅延が作成されたときと同じスレッドに必ずしも付加される必要はなく、(b)進行イベントも処理される可能性があり、(c)遅延/遅延が実現/任意の数のさらなるスレッドが関与してもよい。 –

答えて

9

.thenstd::futureの機能は、今後のC++ 17標準ではproposedです。

Boost's implementation of future(現在の標準に準拠していますが、拡張機能として追加機能を提供しています)は、新しいバージョン(1.53以上)でその機能の一部を提供しています。

future.thenで提供されているように、より安定した制御フローを簡単に実装できるようにするには、より確立されたソリューションについてはBoost.Asio libraryを参照してください。 Asioのコンセプトは、非同期コールバックをディスパッチする中央のio_serviceオブジェクトにアクセスする必要があり、ワーカースレッドを手動で管理する必要があるため、少し複雑です。しかし、原則として、これはあなたが求めたものと非常によくマッチします。

+1

前にAsio。しかし、私が先物について知る前に... それとブーストの未来の組み合わせのように見えますが、私が必要としているものとまったく同じです。すばらしいです。ありがとうございました! – jcoder

2

たとえば、Runnableクラスを実装するオブジェクトをFutureクラスの "then"メソッドに渡すことができます。未来が終わったら、渡されたオブジェクトの "run"メソッドを呼び出します。

+1

これは、仕事をしたスレッドのコールバックを呼び出すでしょう、私はそれを "メイン"スレッドで呼びたいと思います。これを行う理由の1つは、同期の問題を助けることです。 – jcoder

+1

問題は、メインスレッドが他のスレッドが作業を完了するのを単に待つことができないということです。fork-join-frameworkのようなものを使用する必要があります。 – maxdev

+0

これは私がこれを実装しようとしていた場合、何らかの種類のイベントディスパッチループを実行するためにメインスレッドが必要だと言いました。私は完成した先物が何とか自分自身をディスパッチのために待ち行列に入れることを期待しています....私はこれを書くことができました、私は多くのコードを書くことなく同じ目的をより良い方法で達成できるかどうか本当に不思議でした:) – jcoder

4

thenが提案されていますが、名前付き演算子技術を使用してthen独自のインフィックスを実装できます。

struct then_t {};static then_t then;を作成します。 std::future<bool> *then* lambdafutureで待機するstd::asyncを作成し、その結果をlambdaに渡してから、ラムダの戻り値を返すように、左右にoperator*をオーバーライドします。

これは、参照をぶら下げないようにコピーを慎重に作成し、rとlの値構文を使って完全に効率化する必要があるため、多くの注意と注意が必要です。あなたが得る

エンド構文は次のとおりです。あなたが望むものにかなり近いです

aut fut = asyncLoader("cat.jpg"); 
fut *then* [&](Image img) { std::cout << "Image loaded: " << img; }; 

。あなたが本当にスマートであれば、あなたもそれを持っている可能性が

もサポートしています。定型の一部を取り除くと、時には有用であろう

aut fut = asyncLoader("cat.jpg"); 
fut *then* [=] { std::cout << "Image loaded: " << fut.get(); }; 

。これにはfutureの代わりにstd::shared_futureを返すにはasyncLoaderが必要です。

+0

私は持っている質問は、コールバックのスレッドについてです。 asyncLoaderが2番目のスレッドで画像をロードしてそこで未来を完了すると、元のスレッドのコンテキストでコールバックが必要になります。 (だから私はそのスレッドで何らかの種類のディスパッチとイベントループが必要なのです)。たとえ正確な構文でなくても、私が欲しいものを達成するためにasioを使って何かをコーディングすることができるように見えます。 – jcoder

+0

@jcoderが同意しました。元のスレッドのものはいいですね。そのためには、拡張された 'future'を書いてください。これには、拡張された' async'を書くことが含まれます。そのような拡張された未来は、「then」が問題の将来のタスクを実行するスレッドのタスクの待ち行列に新しいタスクを注入することを可能にする。 C++ 11スレッディングプリミティブで実行可能でなければなりません。パッケージタスク、条件変数など – Yakk

2

私はC++の将来を好きではないので、私はここにJavaScriptなどの約束ライブラリ https://github.com/xhawk18/promise-cpp

Defer newDelay(uint64_t timeout) { 
return newPromise([timeout](Defer d) { 
    setTimeout([d]() { 
     d->resolve(); 
    }, timeout); 
}); 

int main() { 
    uv_loop_t *loop = uv_default_loop(); 

    newPromise([](Defer d) { 
     setTimeout([d]() { 
      printf("In timerout 1\n"); 
      d.resolve(893); 
     }, 1000); 
    }).then([](int vv) { 
     printf("In then 1, vv = %d\n", vv); 
     return newDelay(1000); 
    }).then([]() { 
     printf("In then 2\n"); 
     return newDelay(2000); 
    }).then([]() { 
     printf("In then 3\n"); 
     return newDelay(3000); 
    }).then([]() { 
     printf("In last then\n"); 
    }); 

    return uv_run(loop, UV_RUN_DEFAULT); 
} 

だけで、Javascriptの約束と比較書いた -

  1. 利用newPromiseの代わりに、JSの新しいですプロミス
  2. js関数の代わりにラムダを使用
  3. jsの解決の代わりにd.resolveを使用
  4. 使用はd.rejectの代わりのjsのあなたが偶然に任意のタイプの拒否/解決、およびC++のテンプレートに> <の面倒を気にする必要はありませんすることができ

を拒否。