call_once — dynamic package initialization
#include <threads.h>
void call_once(once_flag *flag, void (*init_routine)(void));
once_flag flag = ONCE_FLAG_INIT;
[CX] The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2024 defers to the ISO C standard.The call_once() function shall use the once_flag pointed to by flag to ensure that init_routine is called exactly once, the first time the call_once() function is called with that value of flag. Completion of an effective call to the call_once() function shall synchronize with all subsequent calls to the call_once() function with the same value of flag.
[CX] The call_once() function is not a cancellation point. However, if init_routine is a cancellation point and is canceled, the effect on flag shall be as if call_once() was never called.
If the call to init_routine is terminated by a call to longjmp() or siglongjmp(), the behavior is undefined.
The behavior of call_once() is undefined if flag has automatic storage duration or is not initialized by ONCE_FLAG_INIT.
The call_once() function shall not be affected if the calling thread executes a signal handler during the call.
The call_once() function shall not return a value.
No errors are defined.
None.
If init_routine recursively calls call_once() with the same flag, the recursive call will not call the specified init_routine, and thus the specified init_routine will not complete, and thus the recursive call to call_once() will not return. Use of longjmp() or siglongjmp() within an init_routine to jump to a point outside of init_routine prevents init_routine from returning.
For dynamic library initialization in a multi-threaded process, if an initialization flag is used the flag needs to be protected against modification by multiple threads simultaneously calling into the library. This can be done by using a statically-initialized mutex. However, the better solution is to use call_once() or pthread_once() which are designed for exactly this purpose, for example:
#include <threads.h> static once_flag random_is_initialized = ONCE_FLAG_INIT; extern void initialize_random(void); int random_function() { call_once(&random_is_initialized, initialize_random); ... /* Operations performed after initialization. */ }The call_once() function is not affected by signal handlers for the reasons stated in XRAT B.2.3 Error Numbers.
None.
First released in Issue 8. Included for alignment with the ISO/IEC 9899:2018 standard.
return to top of page