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_flag는call_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는 초기화·설정 코드를 동시 실행에서 정확히 한 번만 수행하고 싶을 때 쓰는 표준 도구예요.