1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
/*!
* This file implements a generic buffer for small, temporary objects.
*
* It is meant for use when keeping track of a large number of allocations
* would be worse in code complexity and performance than keeping some of
* them around until all objects can be discarded at once.
*/
#include <gkscore.h>
#ifndef VALUE_TYPE
#error "VALUE_TYPE must be defined"
#endif
#ifndef VALUE_NAME
#error "VALUE_NAME must be defined"
#endif
#define XCONCAT(LEFT, RIGHT) LEFT ## RIGHT
#define CONCAT(LEFT, RIGHT) XCONCAT(LEFT, RIGHT)
#define MEMORY_NAME CONCAT(VALUE_NAME, _memory_)
#define NEXT_INDEX_NAME CONCAT(VALUE_NAME, _next_index_)
#define SIZE_NAME CONCAT(VALUE_NAME, _memory_size_)
VALUE_TYPE *MEMORY_NAME = NULL;
size_t SIZE_NAME = 0;
size_t NEXT_INDEX_NAME = 0;
size_t CONCAT(copy_, VALUE_NAME)(VALUE_TYPE VALUE_NAME) {
size_t index = NEXT_INDEX_NAME;
if (VALUE_NAME.index) {
return VALUE_NAME.index;
}
if (NEXT_INDEX_NAME >= SIZE_NAME) {
SIZE_NAME += 1024;
MEMORY_NAME = (VALUE_TYPE *)gks_realloc(MEMORY_NAME, sizeof(VALUE_TYPE) * SIZE_NAME);
}
MEMORY_NAME[index] = VALUE_NAME;
MEMORY_NAME[index].index = index + 1;
NEXT_INDEX_NAME += 1;
return index + 1;
}
VALUE_TYPE *CONCAT(get_, VALUE_NAME)(size_t index) {
assert(index <= SIZE_NAME);
if (index == 0) {
return NULL;
}
return MEMORY_NAME + index - 1;
}
void CONCAT(CONCAT(free_, VALUE_NAME), _buffer)() {
if(MEMORY_NAME)
{
gks_free(MEMORY_NAME);
}
MEMORY_NAME = 0;
SIZE_NAME = 0;
NEXT_INDEX_NAME = 0;
}
#undef SIZE_NAME
#undef NEXT_INDEX_NAME
#undef MEMORY_NAME
#undef CONCAT
#undef XCONCAT
#undef VALUE_NAME
#undef VALUE_TYPE
|