call_once — std::call_once

call_once — std::call_once

std::call_once여러 스레드에서 동시에 호출되어도 호출 가능한 객체 f를 정확히 한 번만 실행하는 함수예요. C++11에서 도입됐어요. <mutex> 헤더에 있어요.

스레드 안전한 "한 번만 초기화" 패턴에 사용돼요.

출처: cppreference

본문

// <mutex> 헤더, C++11
template< class Callable, class... Args >
void call_once( std::once_flag& flag, Callable&& f, Args&&... args );

std::call_once가 호출될 때 flag가 아직 완료되지 않음을 나타내면, f를 호출하고, 끝(정상 또는 예외) 후에 flag를 완료 상태로 표시해요. 만약 flag가 이미 완료를 나타내면 f는 호출되지 않아요.

#include <mutex>
#include <iostream>

std::once_flag flag;

void init() {
    std::cout << "초기화\n";
}

void worker() {
    std::call_once(flag, init);   // 정확히 한 번만 실행
}

int main() {
    // 여러 스레드에서 동시에 실행해도 init은 1번만
    std::thread t1(worker), t2(worker), t3(worker);
    t1.join(); t2.join(); t3.join();   // "초기화" 1번만 출력
}

특징

  • 스레드 안전 — 동시 호출에도 하나의 호출만 완주해요.
  • once_flagcall_once와 짝을 이루고, 복사·이동 불가예요.
  • 멤버 함수·생성자 초기화에 자주 쓰여요.
// 싱글턴/정적 초기화 패턴
class Logger {
public:
    static Logger& get() {
        static Logger* inst = nullptr;
        std::call_once(flag, [] { inst = new Logger; });
        return *inst;
    }
private:
    static std::once_flag flag;
};

C++11 static local과 비교

// 더 간단한 방법: 함수 로컬 static (스레드 안전)
static Logger& get() {
    static Logger instance;   // C++11부터 스레드 안전
    return instance;
}

std::call_once는 초기화·설정 코드를 동시 실행에서 정확히 한 번만 수행하고 싶을 때 쓰는 표준 도구예요.

더 알아보기 (Learn more)

cppreference