diff --git a/source/lib/code_generation.h b/source/lib/code_generation.h index d9b8de8ea8..7860426f04 100644 --- a/source/lib/code_generation.h +++ b/source/lib/code_generation.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -23,6 +23,9 @@ #ifndef INCLUDED_CODE_GENERATION #define INCLUDED_CODE_GENERATION +#include +#include + /** * package code into a single statement. * @@ -56,6 +59,30 @@ STMT(\ }\ ) +/** + * execute the code passed as a parameter only the first time each distinct + * value of the key expression is seen. + * + * @param key_expr expression that produces the key to track (e.g., a filename). + * @param code_block code to execute the first time each key value is seen. + * the key expression result is available as 'key' inside the block. + * + * example: + * ONCE_EACH(filename, LOGWARNING("Bad file %s", key)) + * + * may be called at any time (in particular before main), but is not + * thread-safe. + **/ +#define ONCE_EACH(key_expr, code_block) \ +STMT( \ + using KeyType__ = std::decay_t; \ + static std::unordered_set seen__; \ + auto key = (key_expr); \ + if (seen__.insert(key).second) { \ + code_block; \ + } \ +) + /** * execute the code passed as a parameter except the first time this is * reached.