|
#define | _ONCE_AT_QUICK_EXIT_I(NAME, ...) |
|
#define | _ONCE_ATEXIT_I(NAME, ...) |
|
#define | _ONCE_DECLARE(NAME) |
|
#define | _ONCE_DEFINE_I(NAME, ...) |
|
#define | _ONCE_DEFINE_STRONG_I(NAME, ...) |
|
#define | _ONCE_DEPEND_I(NAME, ...) |
|
#define | _ONCE_DEPEND_WEAK_I(NAME, ...) |
|
#define | ONCE_AT_QUICK_EXIT(...) _ONCE_AT_QUICK_EXIT(__VA_ARGS__) |
| Define optional cleanup code that goes with feature named NAME for quick_exit
|
|
#define | ONCE_ATEXIT(...) _ONCE_ATEXIT(__VA_ARGS__) |
| Define optional cleanup code that goes with feature named NAME for atexit
|
|
#define | ONCE_DEFINE(...) _ONCE_DEFINE(__VA_ARGS__) |
| Define the initialization code that goes with feature named NAME
|
|
#define | ONCE_DEFINE_STRONG(...) _ONCE_DEFINE_STRONG(__VA_ARGS__) |
| Similar to ONCE_DEFINE but triggers unconditionally if the platform supports this.
|
|
#define | ONCE_DEPEND(...) _ONCE_DEPEND(__VA_ARGS__) |
| Declare that this TU depends on a initialization and cleanup feature named NAME
|
|
#define | ONCE_DEPEND_WEAK(...) _ONCE_DEPEND_WEAK(__VA_ARGS__) |
| Similar to ONCE_DEPEND but only triggers if ONCE_DEFINE_STRONG is not able to guarantee unconditional initialization.
|
|
|
#define | _ONCE_AT_QUICK_EXIT(...) _ONCE_AT_QUICK_EXIT_I(__VA_ARGS__ __VA_OPT__(,) __UNIT__,) |
|
#define | _ONCE_AT_QUICK_EXIT_CALLBACK(NAME) NAME ∷_Once∷at_quick_exit∷callback |
|
#define | _ONCE_AT_QUICK_EXIT_POINTER(NAME) NAME ∷_Once∷at_quick_exit∷pointer |
|
#define | _ONCE_ATEXIT(...) _ONCE_ATEXIT_I(__VA_ARGS__ __VA_OPT__(,) __UNIT__,) |
|
#define | _ONCE_ATEXIT_CALLBACK(NAME) NAME ∷_Once∷atexit∷callback |
|
#define | _ONCE_ATEXIT_POINTER(NAME) NAME ∷_Once∷atexit∷pointer |
|
#define | _ONCE_CALLBACK(NAME) NAME ∷_Once∷init∷callback |
|
#define | _ONCE_DEFINE(...) _ONCE_DEFINE_I(__VA_ARGS__ __VA_OPT__(,) __UNIT__,) |
|
#define | _ONCE_DEFINE_STRONG(...) _ONCE_DEFINE_STRONG_I(__VA_ARGS__ __VA_OPT__(,) __UNIT__,) |
|
#define | _ONCE_DEPEND(...) _ONCE_DEPEND_I(__VA_ARGS__ __VA_OPT__(,) __UNIT__,) |
|
#define | _ONCE_DEPEND_WEAK(...) _ONCE_DEPEND_WEAK_I(__VA_ARGS__ __VA_OPT__(,) __UNIT__,) |
|
#define | _ONCE_DOTTY_ARC(A, B) "ONCE_DEPEND_MARKER: " A " -> " B |
|
#define | _ONCE_DOTTY_FILE __FILE__ |
|
#define | _ONCE_DOTTY_NODE(A, ...) "ONCE_DEPEND_MARKER: " A " [" #__VA_ARGS__ "]" |
|
#define | _ONCE_INIT(NAME) NAME ∷_Once∷init |
|
#define | _ONCE_IS_STRONG extern |
|
#define | _ONCE_STRONG_FLAG(NAME) NAME ∷_Once∷strong |
|
#define | _ONCE_STRONG_INIT |
|
#define | _ONCE_USER(NAME) NAME ∷_Once∷init∷user |
|
Simple TU initialization and cleanup handling with dependencies.
This is a header only library as a small wrapper around call_once
and atexit
. It has just a handful user interfaces. For triggered dependencies these are
For unconditional dependencies (that should always run) there are
To fully work ONCE_DEFINE_STRONG
needs compiler magic, here we use a gnu feature. ONCE_DEPEND_WEAK
then triggers a dependency just as ONCE_DEPEND
but only if running code unconditionally at startup is not supported. Otherwise this is a no-op.
Currently there is no detection of dependency cycles, but a graph can be extracted from the strings of the binary. It should only have cycles between a symbolic dependency and the TU in which is found.
There is a script called dot_extract.sh
that filters the string of the executable to obtain the graph, which basically looks as follows:
echo "digraph \"$1\" {"
/ONCE_DEPEND_MARKER:/!d
s!ONCE_DEPEND_MARKER:!\t!
s![a-zA-Z_][-+./a-zA-Z0-9_]*!"&"!g
**'
**echo "}"
static char const strings[]
A big char array that contains all the strings together with their null termination.
Definition ellipsis-xml-entities.c:40
Define optional cleanup code that goes with feature named NAME
for atexit
Use this as a prefix to a function definition such as in
}
#define ONCE_ATEXIT(...)
Define optional cleanup code that goes with feature named NAME for atexit
Definition ellipsis-once.h:269
This creates some symbols with internal linkage in the current TU. For this to work ONCE_DEFINE(toto)
has to be defined in the same TU. The other way around, this is not mandatory: ONCE_DEFINE(toto)
can work without having ONCE_ATEXIT(toto)
.
Technically this creates a functions and a function pointer is then used with atexit
. All implicitly defined symbols have internal linkage.
Define the initialization code that goes with feature named NAME
Use this as a prefix to a function definition such as in
}
#define ONCE_DEFINE(...)
Define the initialization code that goes with feature named NAME
Definition ellipsis-once.h:246
#define ONCE_DEPEND(...)
Declare that this TU depends on a initialization and cleanup feature named NAME
Definition ellipsis-once.h:220
This creates some symbols with internal linkage and one external symbol, but with a naming that is not portable between different implementations.
Technically this creates separate functions and a once_flag
that are then used with call_once
.
Use this, even in the same TU, as ONCE_DEPEND(toto)
to be sure that your initialization code is guaranteed to have run before any of your other code.
Declare that this TU depends on a initialization and cleanup feature named NAME
Use this in block scope to refer to the one external symbol that can be used by other TU to indicate a dependency of this TU here.
The external name is not portable between different implementations.
Under the hood that is a simple function call of a void
function.
This can be placed anywhere where a declaration is allowed.