web-dev-qa-db-ja.com

フューチャーとコールバックの使用例と使用パターン

私は最近、主に標準C++に含まれているため、フューチャーに興味を持っています-しかし、Node.jsなどの多くのプログラミング領域で、フューチャーとコールバックについて活発な議論があるようです。

私が知りたいのは、コールバックに(読みやすさと実装の容易さの観点から)フューチャーが明確な利点を提供するよく知られたパターン/ユースケースがあるかどうかです。

私たちは皆、コールバックに関連する主なマイナス面を知っています。コードを読み取るという点での間接性と、JavaScriptのような言語で潜在的に深くネストされて混乱しているラムダです。

Futuresを使用する利点は、コードの間接化を排除し、「同期」スタイルでコードを記述できることですが、バックグラウンド操作のステータスを確認できるハンドラーを提供します。その意味で、未来は人間の心が考える傾向とのより良い構文上の適合であると主張するのに主観的/物議をかもしすぎるとは思わない(これを行う、それを行う、それを待つ間にこれを行うなど)。

ただし、実際にse先物を実際に使用すると、次の問題が頻繁に発生します。

Futuresの典型的な使用例は、vector<future> futures(C++構文を使用)などのfutureオブジェクトの配列を介して多くの非同期操作を管理する場合です。重要な洞察は、先物ではactively各非同期操作をチェックして完了したかどうかを確認する必要があると思いますが、コールバックでは受動的に各イベントが完了するまで待機します。ただし、一般的なケースでは、どのイベントが最初に完了するかを知る方法がないため、futureの配列を反復処理しているときにfuture[10]future[0]ですが、future[0]が完了するのを待っています。

これは、「wait_for」タイプの操作で軽減できます。それぞれの将来を待つ代わりに、一定の短い間隔を待ってから、繰り返しを続けることができます。しかし、これは基本的にビジー待機のようであり、余分なCPUリソースを消費します。コールバックを使用すると、バックグラウンドイベントリアクターによってコールバックコードが受動的に呼び出されるため、これを行う必要はありません。基本的には、アプリケーションコードでフューチャーの配列を反復処理することにより、ポーリングイベントリアクターをより高いレベルで「再実装」することになります。

私が見つけたフューチャーの単純なユースケースの1つは、1つ以上の非同期呼び出しがあり、呼び出し間で一部のCPUサイクルをインターリーブできる状況です。 HTTP Webサービスを2回呼び出す必要があるが、最初の呼び出しの結果は、2番目の呼び出しが完了するのを待たずにすぐに処理を開始する機会を与えていると仮定します。先物はこれを簡単にします。

future result1 = some_remote_call();
object data = result1.get(); // wait for result1 to complete

future result2 = another_remote_call();

// ... do some processing here while we're still waiting on result2 ... //

したがって、これは間違いなくナイスユースケースですが、コールバックを使用するとコードが間接化されるにもかかわらず、Nイベントの発生を待機する一般的なケースはコールバックに適しているようです。

それでは、コールバックよりも先物が(コードの読みやすさと実装の容易さの点で)明確な利点を提供するいくつかのよく知られた使用パターン/ユースケースは何ですか?

3
Siler

あなたが理解する必要があるのは、C++標準ライブラリがおそらく人間が考え得る最悪のフューチャーの実装を持っているということです。 C++が行うことは、セマフォの弱いラッパーに過ぎません。ほとんどの将来の実装では、thenを使用して非同期で複数のフューチャーをチェーンし、他のフューチャーのコレクションに基づく単一のフューチャーを簡単に作成できるように、コールバックラムダの使用を広範囲に奨励しています。彼らはあなたがここで提起している問題のどれも持っていません。

最適な実装の1つについて [〜#〜] q [〜#〜] を見て、futureが実際にどのように使用されるように設計されているかを確認してください。周りを検索すると、それらのアイデアをC++に取り入れている人がいます。自分で実装することはそれほど難しくありません。

4
Karl Bielefeldt