std:: async
|
ヘッダーで定義
<future>
|
||
|
template
<
class
F,
class
...
Args
>
std:: future < /* 詳細は後述 */ > async ( F && f, Args && ... args ) ; |
(1) | (C++11以降) |
|
template
<
class
F,
class
...
Args
>
std::
future
<
/* 詳細は後述 */
>
async
(
std::
launch
policy,
|
(2) | (C++11以降) |
関数テンプレート
std::async
は関数
f
を非同期に(別スレッドで、スレッドプールの一部である可能性もある)実行し、その関数呼び出しの結果を最終的に保持する
std::future
を返します。
std::async
の戻り値の型は
std::
future
<
V
>
であり、ここで
V
は以下を指します:
|
typename
std::
result_of
<
typename
std::
decay
<
F
>
::
type
(
|
(C++17まで) |
|
std:: invoke_result_t < std:: decay_t < F > , std:: decay_t < Args > ... > . |
(C++17から) |
|
以下のいずれかの条件が満たされる場合、プログラムは不適格となる:
|
(C++20以前) |
|
以下のいずれかが false の場合、プログラムは不適格となる:
|
(C++20以降) |
std::async
への呼び出しは、
同期する
f
への呼び出しと、そして
f
の完了は共有状態の準備完了より
前に順序付けられる
。
目次 |
パラメータ
| f | - | Callable を呼び出すオブジェクト |
| args | - | f に渡すパラメータ |
| policy | - | 個々のビットが実行を許可する方法を制御するビットマスク値 |
戻り値
std::future
が、この
std::async
の呼び出しによって作成された共有状態を参照します。
起動ポリシー
非同期呼び出し
async
フラグが設定されている場合、すなわち
(
policy
&
std::
launch
::
async
)
!
=
0
の場合、
std::async
は呼び出しを行います
|
INVOKE
(
decay-copy
(
std::
forward
<
F
>
(
f
)
)
,
|
(C++23まで) |
|
std::
invoke
(
auto
(
std::
forward
<
F
>
(
f
)
)
,
|
(C++23から) |
あたかも std::thread オブジェクトによって表される新しい実行スレッド内であるかのように。
|
decay-copy の呼び出しは現在のスレッドで評価される。 |
(C++23まで) |
|
auto によって生成される値は現在のスレッドで 実体化 される。 |
(C++23以降) |
関数
f
が値を返すか例外をスローする場合、その結果は
std::future
を通じてアクセス可能な共有状態に格納されます。この
std::async
は呼び出し元に返されます。
遅延呼び出し
deferred
フラグが設定されている場合(すなわち
(
policy
&
std::
launch
::
deferred
)
!
=
0
)、
std::async
は保存します
|
decay-copy ( std:: forward < F > ( f ) ) および decay-copy ( std:: forward < Args > ( args ) ) ... を共有状態に格納する。 |
(C++23まで) |
|
auto ( std:: forward < F > ( f ) ) および auto ( std:: forward < Args > ( args ) ) ... を共有状態に格納する。 |
(C++23から) |
遅延評価 が実行されます:
-
非タイムド待機関数の最初の呼び出しが、
std::future
に対して行われる場合、
std::asyncが呼び出し元に返したものは、 INVOKE ( std :: move ( g ) , std :: move ( xyz ) ) を待機関数を呼び出したスレッド(元々std::asyncを呼び出したスレッドである必要はない)で評価する。ここで
|
(C++23まで) |
|
(C++23以降) |
- 結果または例外は、返された std::future に関連付けられた共有状態に配置され、その後初めて準備完了状態となります。同じ std::future への以降のすべてのアクセスは、即座に結果を返します。
その他のポリシー
std::launch::async も std::launch::deferred も、あるいは実装定義のポリシーフラグも policy に設定されていない場合、動作は未定義です。
ポリシー選択
複数のフラグが設定されている場合、どのポリシーが選択されるかは実装定義です。デフォルト( std::launch::async と std::launch::deferred の両方のフラグが policy に設定されている場合)については、標準では利用可能な並行性を活用し、追加のタスクを延期することを推奨(ただし必須ではない)しています。
std::launch::async ポリシーが選択された場合、
-
この
std::async呼び出しによって作成された共有状態を共有する非同期戻りオブジェクトに対する待機関数の呼び出しは、関連するスレッドが完了する(joinされたかのように)か、タイムアウトするまでブロックする;および - 関連するスレッドの完了は、共有状態を待機する最初の関数の成功した戻りと、あるいは共有状態を解放する最後の関数の戻りのいずれか早い方と 同期する 。
例外
例外送出
- std::bad_alloc 、内部データ構造のメモリを確保できない場合、または
-
std::system_error
(エラー条件
std::errc::resource_unavailable_try_again
)が
policy
==
std::
launch
::
async
の場合に、実装が新しいスレッドを開始できないときにスローされる。
- policy が std:: launch :: async | std:: launch :: deferred の場合、または追加のビットが設定されている場合、このケースでは遅延呼び出しまたは実装定義のポリシーにフォールバックする。
注記
実装は、デフォルト起動ポリシーに追加の(実装定義の)ビットを有効にすることで、
std::async
の最初のオーバーロードの動作を拡張する場合があります。
実装定義の起動ポリシーの例としては、同期ポリシー(
std::async
呼び出し内で即時実行)とタスクポリシー(
std::async
と同様だが、スレッドローカル変数がクリアされない)がある。
std::future
から取得された
std::async
の結果がムーブされない場合、または参照にバインドされない場合、
std::future
のデストラクタは完全式の終了時点で非同期操作が完了するまでブロックします。これは実質的に以下のようなコードを同期処理にすることになります:
std::async(std::launch::async, []{ f(); }); // 一時オブジェクトのデストラクタが f() の完了を待機 std::async(std::launch::async, []{ g(); }); // f() が完了するまで実行が開始されない
std::future
のデストラクタは、
std::async
の呼び出し以外の手段で取得された場合、決してブロックしないことに注意してください。
例
#include <algorithm> #include <future> #include <iostream> #include <mutex> #include <numeric> #include <string> #include <vector> std::mutex m; struct X { void foo(int i, const std::string& str) { std::lock_guard<std::mutex> lk(m); std::cout << str << ' ' << i << '\n'; } void bar(const std::string& str) { std::lock_guard<std::mutex> lk(m); std::cout << str << '\n'; } int operator()(int i) { std::lock_guard<std::mutex> lk(m); std::cout << i << '\n'; return i + 10; } }; template<typename RandomIt> int parallel_sum(RandomIt beg, RandomIt end) { auto len = end - beg; if (len < 1000) return std::accumulate(beg, end, 0); RandomIt mid = beg + len / 2; auto handle = std::async(std::launch::async, parallel_sum<RandomIt>, mid, end); int sum = parallel_sum(beg, mid); return sum + handle.get(); } int main() { std::vector<int> v(10000, 1); std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n'; X x; // デフォルトポリシーで (&x)->foo(42, "Hello") を呼び出し: // "Hello 42" を同時に出力するか、実行を延期する可能性があります auto a1 = std::async(&X::foo, &x, 42, "Hello"); // 延期ポリシーで x.bar("world!") を呼び出し // a2.get() または a2.wait() が呼び出されたときに "world!" を出力 auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!"); // asyncポリシーで X()(43) を呼び出し // 同時に "43" を出力 auto a3 = std::async(std::launch::async, X(), 43); a2.wait(); // "world!" を出力 std::cout << a3.get() << '\n'; // "53" を出力 } // この時点で a1 が完了していない場合、a1 のデストラクタがここで "Hello 42" を出力
出力例:
The sum is 10000 43 world! 53 Hello 42
不具合報告
以下の動作変更欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 修正後の動作 |
|---|---|---|---|
| LWG 2021 | C++11 |
遅延評価の場合に戻り値型が不正で、
引数の値カテゴリが不明確 |
戻り値型を修正し、
右辺値が使用されることを明確化 |
| LWG 2078 | C++11 |
std::system_error
がスローされるかどうかが不明確
( policy が std::launch::async 以外の 起動ポリシーを指定する場合) |
スローされるのは
policy == std:: launch :: async の場合のみ |
| LWG 2100 | C++11 |
タイムアウト機能付き待機関数がタイムアウトしない可能性があった
( std::launch::async ポリシーが使用される場合) |
許可 |
| LWG 2120 | C++11 |
標準または実装定義のポリシーが設定されていない場合の
動作が不明確 |
この場合の動作は
未定義 |
| LWG 2186 | C++11 |
遅延評価から返される値とスローされる例外の
扱いが不明確 |
これらは
共有状態に格納される |
| LWG 2752 | C++11 |
std::async
が
std::bad_alloc
をスローしない可能性があった
(内部データ構造のメモリ割り当てに失敗した場合) |
スローする |
| LWG 3476 | C++20 |
(減衰型の)
F
と引数型が直接的に
ムーブ構築可能であることが要求されていた |
これらの要件を削除 [1] |
- ↑ ムーブ構築可能性は既に間接的に std::is_constructible_v によって要求されている。
関連項目
|
(C++11)
|
非同期に設定される値を待機する
(クラステンプレート) |
|
C++ documentation
for
Execution support library
|
|