liveBook · Manning

Call_once

As explained in Modern C

call_once is a C threading function that invokes a specified function exactly once for a given once_flag, synchronizing concurrent callers until that invocation completes.

Use call_once when shared data requires dynamic initialization that cannot be completed before threads are created. Pair the call with one once_flag and one callback; concurrent callers use the same flag before accessing the initialized object. section 18.2

    void call_once(once_flag* flag, void cb(void));


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":8}],[{\"line\":0,\"ch\":9},{\"line\":0,\"ch\":18}],[{\"line\":0,\"ch\":19},{\"line\":0,\"ch\":28}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":8}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":8}]]"}
!@%STYLE%@!

The interface takes a once_flag pointer and a callback with no arguments or return value. section 18.2

Initialize a shared error log

once_flag errlog_flag = ONCE_FLAG_INIT; void errlog_fopen(void) { /* dynamic initialization */ errlog = fopen(/* generated name */, "w"); } void report(double weird) { call_once(&errlog_flag, errlog_fopen); fprintf(errlog, "bad value %g!\n", weird); } The first call among all threads invokes errlog_fopen. Other callers wait until that invocation finishes, then use the initialized errlog without repeating the initialization. section 18.2

The once_flag tracks whether a particular call_once has occurred. It prevents later callback executions and holds concurrent callers until the one initialization callback terminates. This protects initialization, not necessarily the format or ordering of later output. section 18.2

How Modern C covers it

How deep it goes
Explains the interface, callback selection, once_flag state, and waiting behavior, but does not develop implementation internals.
Examples
Demonstrates initializing a shared FILE stream with fopen, setvbuf, and an atexit cleanup callback.
What it assumes
Assumes familiarity with C functions, shared objects, threads, and initialization while contrasting compile-time, main-thread, and deferred initialization.
What you can do after
Operate/configure a once_flag and callback so concurrent callers trigger shared initialization exactly once.
How it connects
Connects call_once with once_flag, dynamic initialization, static storage duration, atexit, and thread-safe shared access.

Also explained in

Compare how 3 books explain call_once →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C. The section links point to the parts of the book it draws on.