A collection of basic/generally desirable code I use across multiple C++ projects.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

225 lines
5.4 KiB

#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;
};