diff --git a/src/rvprof_memory.c b/src/rvprof_memory.c index 8a58553..c1d71d3 100644 --- a/src/rvprof_memory.c +++ b/src/rvprof_memory.c @@ -23,8 +23,6 @@ void rvprof_free(void* ptr, size_t size){ // DYNAMIC ARRAY MANAGEMENT -// used for cleanup callbacks -typedef void* (*cleanup_item_fn_t)(void* item); // generic ensure_capacity implementation, independent of actual array type // maybe if switching to C++ in the future, we may move from pre-processor magic to templates @@ -47,10 +45,45 @@ int name##_array_ensure_capacity(name##_array_t* arr, int needed){ \ type* new_data = rvprof_realloc(arr->data, old_size, new_size); \ if(!new_data){ \ return RVPROF_ERROR_MEMORY; \ - }\ + } \ \ arr->data = new_data; \ arr->capacity = new_capacity; \ - }\ + } \ return RVPROF_SUCCESS;\ -}\ +} + +// do the same for cleanup, taking a fuction alias for the slightly different cleanup logic for each type +#define IMPLEMENT_ARRAY_CLEANUP(type, name, cleanup_fn) \ +void name##_array_cleanup(name##_array_t* arr){ \ + if (arr->data){ \ + for(int i=0; isize; i++){ \ + cleanup_fn(&arr->data[i]); \ + } \ + rvprof_free(arr->data, arr->capacity * sizeof(type)); \ + arr->data = NULL; \ + arr->size = 0; \ + arr->capacity = 0; \ + } \ +} + +// full array implementation macro +#define IMPLEMENT_DYNAMIC_ARRAY(type, name, initial_size, cleanup_fn) \ + IMPLEMENT_ARRAY_ENSURE_CAPACITY(type, name, initial_size) \ + IMPLEMENT_ARRAY_CLEANUP(type, name, cleanup_fn) + +// type-specific cleanups +static void cleanup_region_entry(void* item){ + // region array doesn't need nested cleanup + return; +} + +static void cleanup_symbol_entry(void* item){ + symbol_entry_t* symbol = (symbol_entry_t*)item; + rvprof_free(symbol->name, strlen(symbol->name)+1); + symbol->name = NULL; +} + +// acutal dynamic array implementations: +IMPLEMENT_DYNAMIC_ARRAY(region_t, region, INITIAL_REGIONS, cleanup_region_entry) +IMPLEMENT_DYNAMIC_ARRAY(symbol_entry_t, symbol, INITIAL_SYMBOLS, cleanup_symbol_entry);