wait_for_any / when_any / WaitAny / WhenAny:先物/タスクがゼロになったときの正しい動作は何ですか?

jhcarl0814

when_anyゼロ先物が渡されたときに選択する4つの設計オプションがありますが、残念ながらそれらはすべて理にかなっています。
今まで私はできる

  1. 各設計オプションのいくつかの弱い議論を要約します。
  2. いくつかの実装とそれらが選択する設計オプションをリストします。

設計オプション1:when_any(zero future<T>s)永遠にブロックする未来を返す必要があります。

最初の理由は、定義の単純さと均一性のためです。

when_any(zero futures)が永久にブロックする未来を返す場合、次のようになります。

wait_allは、一部が未完了の間、すべてが完了するまでブロックします。
wait_anyは、すべてが未完了の場合ではなく、一部が終了した場合にブロックを解除します。

when_any(zero futures)がすぐに準備ができている未来を返す場合、次のようになります。

wait_allは、一部が未完了の間、すべてが完了するまでブロックします。
wait_anyは、すべてが未完了の場合ではなく、一部が終了した場合にブロックを解除しますが、先物がゼロの場合はブロックを解除します。

2番目の理由はwhen_any、結合法則と可換二項演算であるため、可変個引数バージョンwhen_anyの場合、when_any演算の単位元(永久にブロックされる未来)を返したいということですまた、独自の二項演算子を定義できる言語(C ++が将来それを行う可能性があります)またはstd::accumulateアルゴリズムがサポートされている言語では、遅かれ早かれこの単位元の問題が発生します。

when_allはのようなものoperator&&であり、パラメータパックの展開では、空のパックがtrueforoperator&&展開さtrueすぐに準備ができている未来のようなものです。
when_anyのようなものoperator||であり、パラメータパックの展開では、空のパックがfalseforoperator||展開さfalse準備ができていない未来のようなものです。

(ID要素が必要な他の場所は次のとおりです。

  • boost::thread::null_mutexto std::scoped_lockstd::scoped_lockより小さなロックを消費し、より大きなロックを生成する結合法則と可換二項演算のようなものです)、
  • std::monostateto std::variantstd::variantより小さな和集合を消費し、より大きな和集合を生成する結合法則と可換二項演算のようなものです)、
  • operator|regexpで空に設定さoperator|ますNFAをregexpに変換するプログラムを作成すると、子がゼロのノードが発生する可能性があります)、
  • operator concat正規表現の空の文字列
  • ..。

発散をどのように扱うべきですか?

プログラムは次のようになります。

  • 値を生成します。
  • エラーを生成します(プログラムの状態が評価関数のドメインから外れます)。
  • 発散(すべての状態Xに対して、次のような状態Yが存在します。X--- [評価関数]-> Y);

発散は値ではなく、発散はエラーではなく、発散は発散です。
オペレーティングシステム、プロトコルスタック、データベースサービス、Webサーバーなど、分岐する(終了しない)プログラムがあります。
発散に対処する方法があります。C#には、キャンセル機能と進捗レポート機能があります。C ++では、実行エージェント(boost.thread)を中断したり、実行エージェント(boost.context、boost.fiber)を破棄したりできます。スレッドセーフなキューまたはチャネルを使用して、アクターとの間で値/エラーを継続的に送受信できます。

発散のユースケース①:

プログラマーはlibrary1を使用して、信頼性の低いネットワーク上の信頼性の低いWebサービスを調べます。ネットワークの信頼性が低いため、library1は永久に再試行します。次の理由により、タイムアウトが期限切れになっときに、 library1自体が例外を共有状態で格納するべきではありません

  1. アプリケーション層のプログラマーは、さまざまなキャンセルメカニズムを使用したい場合があります。
  • タイムアウトが経過したとき、または
  • ユーザーがボタンをクリックしたとき、または
  • ユーザーがボタンをクリックしてタイムアウトを開始し、タイムアウトが期限切れになったとき。
  1. アプリケーション層のプログラマーは、キャンセル時にさまざまなことをしたいと思うかもしれません。
  • デフォルト値を提供する、または
  • 例外を提供する、または
  • 一部のプログラマーは最上位層にいないため、キャンセルメカニズムをアタッチするべきではありません。

とにかく、プログラマーはwhen_any、潜在的にブロックする永遠の未来を彼自身のmy-cancelation / fallback-machanismの未来とマージして、より大きな未来を手に入れる必要があります。
when_any(several future<T>...)リターンfuture<T>想定しているので、フューチャーツリーのすべての中間のwhen_anyノードで定型コードを記述する必要はありません。)
(いくつかの変更が必要です。(1)when_anyリターンが大きいフューチャーは、最初の子フューチャーの準備ができたときに他の子フューチャーを破棄する必要があります。 (2)library1は、promiseオブジェクトを使用しif(shared_state.reference_count == 1)て、コンシューマーが将来を放棄した(つまり、操作がキャンセルされた)ことを確認して認識し、そのループを終了する必要があります;)

発散のユースケース②:

プログラマーはlibrary2を使用して、信頼性の低いネットワーク上の信頼性の低いWebサービスを調べます。library2はn回再試行してから、物理的にではなく論理的に、shared_state(shared_state.diverge = trueまたはstared_state.state = state_t::diverge)にビットを設定することにより、永久にブロックしますプログラマーはwhen_any、library2からの未来とmy-cancelation / fallback-machanismfutureをマージするために使用します。最初の準備ができた子の未来は結果を示します。失敗した子の未来が永久にブロックされるのではなく、例外を除いて準備ができたとすると、後で準備ができた成功した子の未来の代わりに、より大きな未来に答えます。これは望ましくありません。
when_any(several future<T>...)リターンfuture<T>想定しているので、将来のツリーのすべての中間のwhen_anyノードで定型コードを記述する必要はありません。)

発散のユースケース③:

ネットワークコードをテストするときは、ネットワーク状態が非常に悪いクライアントを表す準備ができていないフューチャーを使用し、ネットワーク状態が非常に良いクライアントをすぐに表すことができるフューチャーを使用し、さまざまなタイムアウトのあるフューチャーを使用してスタンドします。間にあるクライアント向け。
(いくつかの変更が必要です:(1)make_diverging_futureを追加します;(2)make_timeout_ready_futureを追加します;)

設計オプション2:when_any(zero future<T>s)例外を含むfutureを返す必要があります。

c ++-std :: when_any()の非ポーリング実装-コードレビュースタック交換https://codereview.stackexchange.com/questions/176168/non-polling-implementation-of-stdwhen-any

並行性TSwhen_anyは、哲学的に-引数なしで呼び出されたときに、準備ができた未来を誤って返します。私のバージョンはそのケースを特別に扱っていないので、自然な振る舞いが失われますpromise。提供された0のいずれかの先物が準備できる前に内部が破壊されwhen_any(/*zero args*/)get()がスローされる準備ができた先物が返されますbroken_promise

これは「早く失敗、大声で失敗」の場合だと思います。彼は発散をエラーとして扱っているため、上記のユースケースでは問題が発生します。

設計オプション3:when_any(zero future<T>s)???の値を含むfutureを返す必要があります。

設計オプション4:when_any(zero future<T>s)禁止する必要があります。

最後の3つの設計オプションは、標準とライブラリによって使用されます。以下で彼らの動機を推測してみます。

* _allおよび* _anyでのいくつかの実装とその動作は次のとおり
です。CPUバウンドプログラムの関数:(テーブルの読み取りに問題がある場合は、編集モードに移動します

どこ 関数 ゼロタスクを通過したときの動作
boost.thread * _all void wait_for_all(...) 戻る void
boost.thread * _any iterator wait_for_any(...) 終了イテレータを返す
boost.fiber * _all void wait_all_simple(...) コンパイル時に拒否されました
vector<R> wait_all_values(...) コンパイル時に拒否されました
vector<R> wait_all_until_error(...) コンパイル時に拒否されました
vector<R> wait_all_collect_errors(...) コンパイル時に拒否されました
R wait_all_members(...) の値を返します R
boost.fiber * _any void wait_first_simple(...) 戻る void
R wait_first_value(...) コンパイル時に拒否されました
R wait_first_outcome(...) コンパイル時に拒否されました
R wait_first_success(...) コンパイル時に拒否されました
variant<R> wait_first_value_het(...) コンパイル時に拒否されました
System.Threading.Tasks * _all void Task.WaitAll(...) 戻る void
System.Threading.Tasks * _any int Task.WaitAny(...) 戻る -1

IOバウンドプログラムの関数:

どこ 関数 ゼロタスクを通過したときの動作
std :: Experimental * _all future<sequence<future<T>>> when_all(...) 空のシーケンスを格納する将来を返します
std :: Experimental * _any future<...> when_any(...) 将来の保管を返す { size index = -1, sequence<future<T>> sequence = empty sequence }
boost.thread * _all future<sequence<future<T>>> when_all(...) 空のシーケンスを格納する将来を返します
boost.thread * _any future<sequence<future<T>>> when_any(...) 空のシーケンスを格納する将来を返します
System.Threading.Tasks * _all Task<TResult[]> Task.WhenAll(...) 空のシーケンスを格納する将来を返します
System.Threading.Tasks * _any Task<Task<TResult>> Task.WhenAny(...) 実行時に拒否されました(throw ArgumentException

System.Threading.Tasks.WaitAny(...)ゼロ先物を受け入れますがSystem.Threading.Tasks.WhenAny(...)、実行時に拒否します。)

when_any(zero tasks)永遠にブロックする未来を返してはいけない理由は、おそらく実用性です。それを許可すると、futureのインターフェースに穴が開いて、すべての未来が潜在的に分岐するため、すべてのアプリケーション層プログラマーはwhen_any、未来をmy-cancelation / fallback-machanism futureとマージして、ブロックされないより大きな未来を取得する必要があります。面倒な詳細情報が不足しています。それを許可しない場合は、すべてのインターフェイスが詳細に文書化されていないチームを保護します(例えを挙げましょう:ライブラリ関数がandのnullptr代わりに潜在的なポインタを受け取り、返すC ++の会社にいると想像してください。詳細や文書optional<reference_wrapper<T>>ありませんが、reference_wrapper<T>すべてのメンバーのアクセス式を次のように保護する必要がありますif(p)、退屈です。先物と同様に、私たちはwhen_any(future_returned_from_library, std::make_timeout_future(1s))どこでもしなければなりません)。したがって、インターフェースと可能性をできるだけ小さくする方がよいでしょう。

(Alan Birtlesに謝罪します:リストされた実装についてその日に間違えたのは残念です:最初の関数以外のboost.fiberのwait_any関数はゼロフューチャーを禁止し、broken_promiseを格納するフューチャーを返す個別の実装があります(https: //codereview.stackexchange.com/questions/176168/non-polling-implementation-of-stdwhen-any)なので、新しい質問にまとめようとしています。)

見る

私は標準的な解決策を選びますhttps//en.cppreference.com/w/cpp/experimental/when_any

  1. 範囲が空の場合(つまり、first == last)、返されるfutureはすぐに準備ができています。when_any_resultのfuturesフィールドは空のベクトルであり、indexフィールドはsize_t(-1)です。
  2. 引数が指定されていない場合、返されるfutureはすぐに準備ができています。when_any_resultのfuturesフィールドは空のタプルであり、indexフィールドはsize_t(-1)です。

また、他の「潜在的に望ましい動作」のほとんどは、受信したリストに「空の」シードフューチャーを追加するだけで簡単に構成できることにも注意してください。

 auto my_when_any = [](auto... f) {
     return when_any(EmptyT{}, f...);
 };

ここではEmptyT、常に準備ができている将来の可能性があり、準備ができてことはありませんか、あなたの好みに応じて例外を保持しています。

これは、例えば倍の表現に非常によく似ていますがmonoidal「シード」を決める:(false || ... || pack)(true && ... && pack)あなたが参照されます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

std :: when_anyが結果タイプとしてstd :: vectorではなくstd :: tupleを使用するのはなぜですか?

分類Dev

Task.WaitAnyの最大タスク?

分類Dev

WaitAny()でWaitHandlesの配列を使用する

分類Dev

Task.WaitAny()—結果の確認

分類Dev

typescriptは、noImplicitAnyがオンのときにメッセージとともにTS7017エラーをスローします。タイプ「{}」にはインデックス署名がないため、要素には暗黙的に「any」タイプがあります。

分類Dev

タイプ 'string'の式はインデックスに使用できないため、要素は暗黙的に 'any'タイプを持っています

分類Dev

「Box <Any>でパニックになりました」というメッセージでテストが失敗するのはなぜですか?

分類Dev

xs:anyがjaxbクラスと自動バインドされないのはなぜですか?

分類Dev

Any / All python short-circuit:次のように動作しないのはなぜですか?

分類Dev

Typescriptエラー:タイプ「string」の式を使用してタイプにインデックスを付けることができないため、要素には暗黙的に「any」タイプがあります

分類Dev

List <List <Any >>が指定されたときに、Parameterized JUnitテストに対してIllegalArgumentExceptionがスローされるのに、List <Array <Any >>で機能するのはなぜですか。

分類Dev

Pythonのany / allが見つかったオブジェクトを返さないのはなぜですか?

分類Dev

any_instanceなしでメソッド呼び出しが行われなかったことを表明するにはどうすればよいですか?

分類Dev

any()がTrueを返す原因となった値を取得するにはどうすればよいですか?

分類Dev

構文の目的/動作は何ですか(<any> new Classname)

分類Dev

Angular / TypeScriptでfloatTheadを使用するとエラープロパティ 'floatThead'がタイプ 'JQuery <any>'に存在しないのはなぜですか

分類Dev

TypeScript TS7015:インデックス式がタイプ 'number'ではないため、要素は暗黙的に 'any'タイプを持っています

分類Dev

Typescriptの()=> anyと{():any}の違いは何ですか

分類Dev

Is there any 'group async wait' for sidekiq's tasks?

分類Dev

@ sys.anyがテキストを正しくキャプチャしないのはなぜですか?

分類Dev

anyとany []の違いは何ですか?

分類Dev

エラーTS7052:タイプ 'AbstractControl'にはインデックス署名がないため、要素には暗黙的に 'any'タイプがあります。「get」と呼ぶつもりでしたか?

分類Dev

.xsを介してスライスしながらmultiIndexDataFrameでany()とall()を使用する:奇妙な動作または私だけ?

分類Dev

typescript:Element のプロトタイプには、タイプ '_BaseOption' にインデックス署名がないため、暗黙的に 'any' タイプがあります。

分類Dev

[SomeStruct]が[Any]に変換できないのはなぜですか?

分類Dev

no-unsafe-anyが有効になっているのに、tslintが強く型付けされたパラメーターのプロパティにフラグを立てるのはなぜですか

分類Dev

Rプログラミングでは、anyと|の違いは何ですか。(または)ブール演算子?

分類Dev

mypyがAnyを戻りアノテーションとして文句を言うのはなぜですか?また、何でもよい戻り値にどのようにアノテーションを付ける必要がありますか?

分類Dev

タイプ `* const Any`の何かによってキー設定された` HashMap`を作成することは可能ですか?

Related 関連記事

  1. 1

    std :: when_anyが結果タイプとしてstd :: vectorではなくstd :: tupleを使用するのはなぜですか?

  2. 2

    Task.WaitAnyの最大タスク?

  3. 3

    WaitAny()でWaitHandlesの配列を使用する

  4. 4

    Task.WaitAny()—結果の確認

  5. 5

    typescriptは、noImplicitAnyがオンのときにメッセージとともにTS7017エラーをスローします。タイプ「{}」にはインデックス署名がないため、要素には暗黙的に「any」タイプがあります。

  6. 6

    タイプ 'string'の式はインデックスに使用できないため、要素は暗黙的に 'any'タイプを持っています

  7. 7

    「Box <Any>でパニックになりました」というメッセージでテストが失敗するのはなぜですか?

  8. 8

    xs:anyがjaxbクラスと自動バインドされないのはなぜですか?

  9. 9

    Any / All python short-circuit:次のように動作しないのはなぜですか?

  10. 10

    Typescriptエラー:タイプ「string」の式を使用してタイプにインデックスを付けることができないため、要素には暗黙的に「any」タイプがあります

  11. 11

    List <List <Any >>が指定されたときに、Parameterized JUnitテストに対してIllegalArgumentExceptionがスローされるのに、List <Array <Any >>で機能するのはなぜですか。

  12. 12

    Pythonのany / allが見つかったオブジェクトを返さないのはなぜですか?

  13. 13

    any_instanceなしでメソッド呼び出しが行われなかったことを表明するにはどうすればよいですか?

  14. 14

    any()がTrueを返す原因となった値を取得するにはどうすればよいですか?

  15. 15

    構文の目的/動作は何ですか(<any> new Classname)

  16. 16

    Angular / TypeScriptでfloatTheadを使用するとエラープロパティ 'floatThead'がタイプ 'JQuery <any>'に存在しないのはなぜですか

  17. 17

    TypeScript TS7015:インデックス式がタイプ 'number'ではないため、要素は暗黙的に 'any'タイプを持っています

  18. 18

    Typescriptの()=> anyと{():any}の違いは何ですか

  19. 19

    Is there any 'group async wait' for sidekiq's tasks?

  20. 20

    @ sys.anyがテキストを正しくキャプチャしないのはなぜですか?

  21. 21

    anyとany []の違いは何ですか?

  22. 22

    エラーTS7052:タイプ 'AbstractControl'にはインデックス署名がないため、要素には暗黙的に 'any'タイプがあります。「get」と呼ぶつもりでしたか?

  23. 23

    .xsを介してスライスしながらmultiIndexDataFrameでany()とall()を使用する:奇妙な動作または私だけ?

  24. 24

    typescript:Element のプロトタイプには、タイプ '_BaseOption' にインデックス署名がないため、暗黙的に 'any' タイプがあります。

  25. 25

    [SomeStruct]が[Any]に変換できないのはなぜですか?

  26. 26

    no-unsafe-anyが有効になっているのに、tslintが強く型付けされたパラメーターのプロパティにフラグを立てるのはなぜですか

  27. 27

    Rプログラミングでは、anyと|の違いは何ですか。(または)ブール演算子?

  28. 28

    mypyがAnyを戻りアノテーションとして文句を言うのはなぜですか?また、何でもよい戻り値にどのようにアノテーションを付ける必要がありますか?

  29. 29

    タイプ `* const Any`の何かによってキー設定された` HashMap`を作成することは可能ですか?

ホットタグ

アーカイブ