#include "alloc.h" #include "string.h" #include "print.h" #include "types.h" #if false static void* leakcheckMalloc(size_t size, const char* file, s32 line) { ULE_TYPES_H_FTAG; return malloc(size); } static void* leakcheckCalloc(size_t maxNumOfElements, size_t elementSize, const char* file, s32 line) { ULE_TYPES_H_FTAG; return calloc(maxNumOfElements, elementSize); } static void* leakcheckRealloc(void* buffer, size_t newSize, const char* file, s32 line) { ULE_TYPES_H_FTAG; return realloc(buffer, newSize); } static void leakcheckFree(void* ptr, const char* file, s32 line) { ULE_TYPES_H_FTAG; free(ptr); } #define malloc(size) leakcheckMalloc(size, __FILE__, __LINE__) #define calloc(numElements, size) leakcheckCalloc(numElements, size, __FILE__, __LINE__) #define realloc(buffer, newSize) leakcheckRealloc(buffer, newSize, __FILE__, __LINE__) #define free(ptr) leakcheckFree(ptr, __FILE__, __LINE__) static void dumpLeaks() { void* address; size_t size; const char* file; s32 line; for (;;) { println("%p - %lu, %s:%d", address, size, file, line); } } #endif // system allocators void* pMalloc(size_t size) { ULE_TYPES_H_FTAG; void* p = malloc(size); if (!p) { die("Out of memory!n\nfailed to malloc %p with size %u\n", p, size); } return p; } void* pMalloc(size_t size, void* allocatorState) { ULE_TYPES_H_FTAG; return pMalloc(size); } void* pCalloc(size_t maxNumOfElements, size_t elementSize) { ULE_TYPES_H_FTAG; void* p = calloc(maxNumOfElements, elementSize); if (!p) { die("Out of memory!\nfailed to calloc %p with %u elements of size %u\n", p, maxNumOfElements, elementSize); } return p; } void* pCalloc(size_t maxNumOfElements, size_t elementSize, void* allocatorState) { ULE_TYPES_H_FTAG; return pCalloc(maxNumOfElements, elementSize); } void* pRealloc(void* buffer, size_t newSize) { ULE_TYPES_H_FTAG; void* p = realloc(buffer, newSize); if (!p) { //pFree(buffer); // if we ever *don't* terminate the program at this point, we should free |buffer| die("Out of memory!\nfailed to realloc %p with size: %u\n", buffer, newSize); } return p; } void* pRealloc(void* buffer, size_t newSize, void* allocatorState) { ULE_TYPES_H_FTAG; return pRealloc(buffer, newSize); } void pFree(void* ptr) { ULE_TYPES_H_FTAG; free(ptr); } void pFree(void* ptr, void* allocatorState) { ULE_TYPES_H_FTAG; pFree(ptr); } void pFree(const void* ptr) { ULE_TYPES_H_FTAG; pFree((void*) ptr); } void pFree(const void* ptr, void* allocatorState) { ULE_TYPES_H_FTAG; pFree((void*) ptr, allocatorState); } #ifdef malloc #undef malloc #endif #ifdef calloc #undef calloc #endif #ifdef realloc #undef realloc #endif #ifdef free #undef free #endif static bool DefaultAllocatorInited = false; static Allocator DefaultAllocator; static void defaultAllocatorInit() { ULE_TYPES_H_FTAG; DefaultAllocator.state = null; DefaultAllocator.mallocate = pMalloc; DefaultAllocator.callocate = pCalloc; DefaultAllocator.reallocate = pRealloc; DefaultAllocator.free = pFree; DefaultAllocatorInited = true; } Allocator& Allocator :: GetDefault() { ULE_TYPES_H_FTAG; if (!DefaultAllocatorInited) defaultAllocatorInit(); return DefaultAllocator; } //================================================================================ // alignment should be a power of 2 static u64 alignForward2(u64 ptr, size_t alignment) { ULE_TYPES_H_FTAG; u64 p, a, modulo; p = ptr; a = alignment; modulo = p & (a - 1); if (modulo != 0) { p += a - modulo; } return p; } static u64 alignForward(u64 ptr, size_t alignment) { ULE_TYPES_H_FTAG; return ((ptr + alignment - 1) / alignment) * alignment; } //================================================================================ // Scratch/Arena Arena* Arena :: Init(u32 sizeInBytes) { ULE_TYPES_H_FTAG; Arena* arena = (Arena*) pMalloc(sizeof(Arena)); arena->index = 0; arena->buffer = (u8*) pMalloc(sizeof(u8) * sizeInBytes); arena->bufferSizeInBytes = sizeInBytes; return arena; } void* Arena :: Alloc(u32 sizeInBytes) { ULE_TYPES_H_FTAG; u8* p = this->buffer + this->index; u8* end = this->buffer + this->bufferSizeInBytes; if ((p + sizeInBytes) >= end) { return null; } this->index += sizeInBytes; return (void*) p; /* u8* p = this->buffer + this->index; u32 offset = (u32) alignForward2((u64) p, 64); //String::memset(p, 0, sizeInBytes); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" if ((void*)(offset + sizeInBytes) <= (this->buffer + this->bufferSizeInBytes)) { #pragma clang diagnostic pop void* ptr = &this->buffer[offset]; this->index += offset + sizeInBytes; String::memset(ptr, 0, sizeInBytes); return ptr; } return null; */ } void Arena :: Clear() { ULE_TYPES_H_FTAG; this->index = 0; } float Arena :: PercentUsed() { ULE_TYPES_H_FTAG; return ((float)this->index)/((float)this->bufferSizeInBytes); } //================================================================================ struct StackAllocator { u32 bufferSize; u32 index; u8* buffer; }; struct PoolAllocator { u8* buffer; };