Created
April 6, 2017 11:51
-
-
Save primiano/2ad94f6f822ff6b1a730873cab611f2b to your computer and use it in GitHub Desktop.
tracing_macros_constexpr.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <string.h> | |
struct Category { | |
const char *name; | |
uint8_t is_enabled; | |
}; | |
constexpr uint32_t N = 100; | |
constexpr Category kKnownCategories[N] = {{"foo", false}, {"bar", false}}; | |
Category g_categories[N] = { | |
// Having to do these assignments is really awkward. But I don't know | |
// enough constexpr magic to be able to just assign the array to the | |
// constexpr one. | |
kKnownCategories[0], kKnownCategories[1], | |
}; | |
constexpr uint8_t *GetEnabledPtrAtCompileTime(const char *cat, uint32_t i = 0) { | |
// Apologies for the nested ternary operators, but any other more readable | |
// option (if statements, variables) was a C++14 extension. | |
return (kKnownCategories[i].name == nullptr) | |
? nullptr | |
: ((cat == kKnownCategories[i].name) | |
? &g_categories[i].is_enabled | |
: (GetEnabledPtrAtCompileTime(cat, i + 1))); | |
} | |
uint8_t* __attribute__ ((noinline)) GetEnabledPtrAtRunTime(const char *cat) { | |
// Assume this has the proper locks for thread-safety. | |
for (uint32_t i = 0; i < N; i++) { | |
// Reached empty slot, just append the new cat. | |
if (g_categories[i].name == nullptr) | |
g_categories[i].name = cat; | |
if (strcmp(g_categories[i].name, cat) == 0) | |
return &g_categories[i].is_enabled; | |
} | |
// more than 100 categories. the real implementation has a fallback for this. | |
return nullptr; | |
} | |
void __attribute__ ((noinline)) AddEvent(const char *cat, const char *evt_name) { | |
// LOL, assume this does TraceLog::GetInstance()->AddTraceEvent(...). | |
printf("EVT: %s %s (ptr: %p)\n", cat, evt_name, GetEnabledPtrAtRunTime(cat)); | |
} | |
#define TOKENPASTE(x, y) x##y | |
#define TOKENPASTE2(x, y) TOKENPASTE(x, y) | |
#define UNIQUE_VAR TOKENPASTE2(var, __LINE__) | |
#define TRACE_EVENT0(cat, event_name) \ | |
static uint8_t *UNIQUE_VAR = nullptr; \ | |
if (GetEnabledPtrAtCompileTime(cat)) { \ | |
UNIQUE_VAR = GetEnabledPtrAtCompileTime(cat); \ | |
} else if (UNIQUE_VAR == nullptr) { \ | |
UNIQUE_VAR = GetEnabledPtrAtRunTime(cat); \ | |
printf("Dynamically getting pointer '%s' : %p\n", cat, UNIQUE_VAR); \ | |
} \ | |
do { \ | |
if (*((volatile uint8_t *)UNIQUE_VAR)) \ | |
AddEvent(cat, event_name); \ | |
} while (0) | |
void foo() { TRACE_EVENT0("foo", "foo::something"); } | |
void baz() { TRACE_EVENT0("baz", "baz::something"); } | |
int main() { | |
for (int i = 0; i < 2; i++) { | |
// Initial iteration is for warming up categories. | |
TRACE_EVENT0("foo", "foo::something"); | |
TRACE_EVENT0("bar", "bar::something"); | |
TRACE_EVENT0("baz", "baz::something"); | |
// Enable tracing: | |
for (uint32_t i = 0; i < N && g_categories[i].name; i++) | |
g_categories[i].is_enabled = true; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment