on first look task is very simply, can be next code:
void func()
{
static LONG first = TRUE;
if (_InterlockedExchange(&first, FALSE))
{
subfunc();
}
// some code
}
this give 100% guarantee that subfunc()
will be called once and only once even if several thread in concurrent call your func()
but what be if // some code
depended on result of subfunc
? in this case task become already not trivial. need some synchronization. and here already depended from os or compiler. in Windows, begin from Vista understand this problem and add function InitOnceExecuteOnce
- read Using One-Time Initialization
if your subfunc()
have no in and out parameters code can be very simply:
BOOL CALLBACK InitOnceCallback(PINIT_ONCE /*InitOnce*/, PVOID /*Parameter*/,PVOID* /*Context*/)
{
subfunc();
return TRUE;
}
void func()
{
static INIT_ONCE once = RTL_RUN_ONCE_INIT;
if (InitOnceExecuteOnce(&once, InitOnceCallback, 0, 0))
{
// somecode
}
// error init
}
also some modern compilers can correct handle static one time initialization. say latest versions of CL
. with it code can be next:
void func()
{
static char tag = (subfunc(), 0);
// some code
}
here CL
internally call special functions (implemented in CRT) _Init_thread_header
, _Init_thread_footer
- implementation can be look in crt source code - thread_safe_statics.cpp