std:: call_once
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
定義済みヘッダー
<mutex>
|
||
|
template
<
class
Callable,
class
...
Args
>
void call_once ( std:: once_flag & flag, Callable && f, Args && ... args ) ; |
(C++11以降) | |
Callable オブジェクト f を正確に一度だけ実行します。複数のスレッドから同時に呼び出された場合でも同様です。
詳細:
-
std::call_onceが呼び出された時点で、 flag が f の呼び出しが既に完了していることを示している場合、std::call_onceは直ちに制御を返す(このようなstd::call_onceの呼び出しは passive として知られる)。
-
それ以外の場合、
std::call_onceは INVOKE ( std:: forward < Callable > ( f ) , std:: forward < Args > ( args ) ... ) を呼び出します。 std::thread コンストラクタや std::async とは異なり、引数は別の実行スレッドに転送する必要がないため、移動やコピーは行われません(このようなstd::call_onceの呼び出しは アクティブ として知られています)。
-
-
その呼び出しが例外を送出した場合、その例外は
std::call_onceの呼び出し元に伝播され、 flag は反転されないため、別の呼び出しが試行されます(このようなstd::call_onceの呼び出しは exceptional (例外的呼び出し)として知られています)。 -
その呼び出しが正常に戻った場合(このような
std::call_onceの呼び出しは returning (戻り呼び出し)として知られています)、 flag が反転され、同じ flag を持つ他のすべてのstd::call_once呼び出しは passive (受動的)であることが保証されます。
-
その呼び出しが例外を送出した場合、その例外は
同じ flag 上のすべての アクティブ な呼び出しは、ゼロ個以上の 例外送出 呼び出しと、それに続く1つの 正常復帰 呼び出しから成る単一の全順序を形成します。各 アクティブ 呼び出しの終了は、その順序における次の アクティブ 呼び出しと同期します。
returning
呼び出しからの戻りは、同じ
flag
に対するすべての
passive
呼び出しからの戻りと同期します(synchronizes-with):これは、
std::call_once
へのすべての同時呼び出しが、
active
呼び出しによって行われた副作用を、追加の同期なしで確実に観察することを保証します。
目次 |
パラメータ
| flag | - | 正確に関数が1つだけ実行されるオブジェクト |
| f | - | Callable 呼び出し可能なオブジェクト |
| args... | - | 関数に渡す引数 |
戻り値
(なし)
例外
-
std::system_error
が、指定された通りに
std::call_onceの呼び出しが実行されるのを妨げる状態が発生した場合。 - f によってスローされるあらゆる例外。
注記
std::call_once
への同時呼び出しが異なる関数
f
を渡した場合、どの
f
が呼び出されるかは未規定です。選択された関数は、それが渡された
std::call_once
呼び出しと同じスレッドで実行されます。
関数内静的変数の初期化は、複数のスレッドから呼び出された場合でも一度だけ発生することが保証されており、
std::call_once
を使用した同等のコードよりも効率的である可能性があります。
この関数のPOSIXに相当するものは
pthread_once
です。
例
#include <iostream> #include <mutex> #include <thread> std::once_flag flag1, flag2; void simple_do_once() { std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; }); } void may_throw_function(bool do_throw) { if (do_throw) { std::cout << "Throw: call_once will retry\n"; // これは複数回表示される可能性がある throw std::exception(); } std::cout << "Did not throw, call_once will not attempt again\n"; // 1回のみ保証 } void do_once(bool do_throw) { try { std::call_once(flag2, may_throw_function, do_throw); } catch (...) {} } int main() { std::thread st1(simple_do_once); std::thread st2(simple_do_once); std::thread st3(simple_do_once); std::thread st4(simple_do_once); st1.join(); st2.join(); st3.join(); st4.join(); std::thread t1(do_once, true); std::thread t2(do_once, true); std::thread t3(do_once, false); std::thread t4(do_once, true); t1.join(); t2.join(); t3.join(); t4.join(); }
出力例:
Simple example: called once Throw: call_once will retry Throw: call_once will retry Throw: call_once will retry Did not throw, call_once will not attempt again
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| LWG 2080 | C++11 |
std::invalid_argument
がスローされる(
f
が無効な場合)、
ただし f が無効化されるシナリオは規定されていない |
このエラー条件を削除 |
| LWG 2442 | C++11 | 引数は呼び出し前にコピーおよび/またはムーブされていた | コピー/ムーブは行われない |
関連項目
|
(C++11)
|
call_once
が関数を一度だけ呼び出すことを保証するためのヘルパーオブジェクト
(クラス) |
|
Cドキュメント
for
call_once
|
|