Namespaces
Variants

std:: call_once

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
(C++11)
(C++11)
(C++11)
call_once
(C++11)
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
헤더에 정의됨 <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