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호출은 active 로 알려져 있습니다).
-
-
해당 호출이 예외를 발생시키면, 이는
std::call_once의 호출자에게 전파되며, flag 가 반전되지 않아 다른 호출이 시도될 수 있습니다 (이러한std::call_once호출은 exceptional 로 알려져 있습니다). -
해당 호출이 정상적으로 반환되면 (이러한
std::call_once호출은 returning 으로 알려져 있습니다), flag 가 반전되고, 동일한 flag 를 사용하는 다른 모든std::call_once호출은 passive 상태가 됨이 보장됩니다.
-
해당 호출이 예외를 발생시키면, 이는
동일한 flag 상의 모든 활성 호출들은 단일 전체 순서를 형성하며, 이는 0개 이상의 예외 호출과 그 뒤를 잇는 하나의 반환 호출로 구성됩니다. 각 활성 호출의 종료는 해당 순서에서 다음 활성 호출과 동기화됩니다.
returning
호출로부터의 반환은 동일한
flag
에 대한 모든
passive
호출들의 반환과 동기화됩니다:
이는
std::call_once
에 대한 모든 동시 호출이
active
호출에 의해 만들어진 모든 부수 효과를
추가적인 동기화 없이 관찰할 수 있음을 보장합니다.
목차 |
매개변수
| flag | - | 정확히 하나의 함수가 실행되는 객체 |
| 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"; // 한 번만 보장됨 } 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
|
|