This is a part of code that I'm trying to understand but I can't understand how a macro like this works. The first line #define FOREACH_OMPD_STATE(macro)
defines a function_like Macro that has a parameter named 'macro' but what does the rest of the definition mean?
#define FOREACH_OMPD_STATE(macro) \
\
/* first available state */ \
macro (ompt_state_undefined, 0x102) /* undefined thread state */ \
\
/* work states (0..15) */ \
macro (ompt_state_work_serial, 0x000) /* working outside parallel */ \
macro (ompt_state_work_parallel, 0x001) /* working within parallel */ \
macro (ompt_state_work_reduction, 0x002) /* performing a reduction */
Are those different values for the parameter named macro or what?
CodePudding user response:
FOREACH_OMPD_STATE
is an X macro. It provides a list that is used by passing various macros to do things with the list items. For example, we can use a macro that produces only the names to make a list of enum
identifiers:
#define NameOnly(name, value) name,
enum { FOREACH_OMPD_STATE(NameOnly) };
That code generates (line formatting added for readability):
enum {
ompt_state_undefined,
ompt_state_work_serial,
ompt_state_work_parallel,
ompt_state_work_reduction,
};
Having done that, we could use a different macro that creates array initializers to fill an array indexed by the enum
identifiers with the values provided by the FOREACH_OMPD_STATE
macro:
#define MakeInitializer(name, value) [name] = value,
int ArrayOfValues[] = { FOREACH_OMPD_STATE(MakeInitializer) };
That generates (line formatting added for readability):
int ArrayOfValues = {
[ompt_state_undefined] = 0x102,
[ompt_state_work_serial] = 0x000,
[ompt_state_work_parallel] = 0x001,
[ompt_state_work_reduction] = 0x002,
};
The key idea is we only need to list the names and values once in the source code, in defining the FOREACH_OMPD_STATE
macro, and then can use them in diverse ways later without repeating them.