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

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. #include "alloc.h"
  2. #include "string.h"
  3. #include "print.h"
  4. #include "types.h"
  5. #if false
  6. static void* leakcheckMalloc(size_t size, const char* file, s32 line) {
  7. ULE_TYPES_H_FTAG;
  8. return malloc(size);
  9. }
  10. static void* leakcheckCalloc(size_t maxNumOfElements, size_t elementSize, const char* file, s32 line) {
  11. ULE_TYPES_H_FTAG;
  12. return calloc(maxNumOfElements, elementSize);
  13. }
  14. static void* leakcheckRealloc(void* buffer, size_t newSize, const char* file, s32 line) {
  15. ULE_TYPES_H_FTAG;
  16. return realloc(buffer, newSize);
  17. }
  18. static void leakcheckFree(void* ptr, const char* file, s32 line) {
  19. ULE_TYPES_H_FTAG;
  20. free(ptr);
  21. }
  22. #define malloc(size) leakcheckMalloc(size, __FILE__, __LINE__)
  23. #define calloc(numElements, size) leakcheckCalloc(numElements, size, __FILE__, __LINE__)
  24. #define realloc(buffer, newSize) leakcheckRealloc(buffer, newSize, __FILE__, __LINE__)
  25. #define free(ptr) leakcheckFree(ptr, __FILE__, __LINE__)
  26. static void dumpLeaks() {
  27. void* address;
  28. size_t size;
  29. const char* file;
  30. s32 line;
  31. for (;;) {
  32. println("%p - %lu, %s:%d", address, size, file, line);
  33. }
  34. }
  35. #endif
  36. // system allocators
  37. void* pMalloc(size_t size) {
  38. ULE_TYPES_H_FTAG;
  39. void* p = malloc(size);
  40. if (!p) {
  41. die("Out of memory!n\nfailed to malloc %p with size %u\n", p, size);
  42. }
  43. return p;
  44. }
  45. void* pMalloc(size_t size, void* allocatorState) {
  46. ULE_TYPES_H_FTAG;
  47. return pMalloc(size);
  48. }
  49. void* pCalloc(size_t maxNumOfElements, size_t elementSize) {
  50. ULE_TYPES_H_FTAG;
  51. void* p = calloc(maxNumOfElements, elementSize);
  52. if (!p) {
  53. die("Out of memory!\nfailed to calloc %p with %u elements of size %u\n", p, maxNumOfElements, elementSize);
  54. }
  55. return p;
  56. }
  57. void* pCalloc(size_t maxNumOfElements, size_t elementSize, void* allocatorState) {
  58. ULE_TYPES_H_FTAG;
  59. return pCalloc(maxNumOfElements, elementSize);
  60. }
  61. void* pRealloc(void* buffer, size_t newSize) {
  62. ULE_TYPES_H_FTAG;
  63. void* p = realloc(buffer, newSize);
  64. if (!p) {
  65. //pFree(buffer); // if we ever *don't* terminate the program at this point, we should free |buffer|
  66. die("Out of memory!\nfailed to realloc %p with size: %u\n", buffer, newSize);
  67. }
  68. return p;
  69. }
  70. void* pRealloc(void* buffer, size_t newSize, void* allocatorState) {
  71. ULE_TYPES_H_FTAG;
  72. return pRealloc(buffer, newSize);
  73. }
  74. void pFree(void* ptr) {
  75. ULE_TYPES_H_FTAG;
  76. free(ptr);
  77. }
  78. void pFree(void* ptr, void* allocatorState) {
  79. ULE_TYPES_H_FTAG;
  80. pFree(ptr);
  81. }
  82. void pFree(const void* ptr) {
  83. ULE_TYPES_H_FTAG;
  84. pFree((void*) ptr);
  85. }
  86. void pFree(const void* ptr, void* allocatorState) {
  87. ULE_TYPES_H_FTAG;
  88. pFree((void*) ptr, allocatorState);
  89. }
  90. #ifdef malloc
  91. #undef malloc
  92. #endif
  93. #ifdef calloc
  94. #undef calloc
  95. #endif
  96. #ifdef realloc
  97. #undef realloc
  98. #endif
  99. #ifdef free
  100. #undef free
  101. #endif
  102. static bool DefaultAllocatorInited = false;
  103. static Allocator DefaultAllocator;
  104. static void defaultAllocatorInit() {
  105. ULE_TYPES_H_FTAG;
  106. DefaultAllocator.state = null;
  107. DefaultAllocator.mallocate = pMalloc;
  108. DefaultAllocator.callocate = pCalloc;
  109. DefaultAllocator.reallocate = pRealloc;
  110. DefaultAllocator.free = pFree;
  111. DefaultAllocatorInited = true;
  112. }
  113. Allocator& Allocator :: GetDefault() {
  114. ULE_TYPES_H_FTAG;
  115. if (!DefaultAllocatorInited) defaultAllocatorInit();
  116. return DefaultAllocator;
  117. }
  118. //================================================================================
  119. // alignment should be a power of 2
  120. static u64 alignForward2(u64 ptr, size_t alignment) {
  121. ULE_TYPES_H_FTAG;
  122. u64 p, a, modulo;
  123. p = ptr;
  124. a = alignment;
  125. modulo = p & (a - 1);
  126. if (modulo != 0) {
  127. p += a - modulo;
  128. }
  129. return p;
  130. }
  131. static u64 alignForward(u64 ptr, size_t alignment) {
  132. ULE_TYPES_H_FTAG;
  133. return ((ptr + alignment - 1) / alignment) * alignment;
  134. }
  135. //================================================================================
  136. // Scratch/Arena
  137. Arena* Arena :: Init(u32 sizeInBytes) {
  138. ULE_TYPES_H_FTAG;
  139. Arena* arena = (Arena*) pMalloc(sizeof(Arena));
  140. arena->index = 0;
  141. arena->buffer = (u8*) pMalloc(sizeof(u8) * sizeInBytes);
  142. arena->bufferSizeInBytes = sizeInBytes;
  143. return arena;
  144. }
  145. void* Arena :: Alloc(u32 sizeInBytes) {
  146. ULE_TYPES_H_FTAG;
  147. u8* p = this->buffer + this->index;
  148. u8* end = this->buffer + this->bufferSizeInBytes;
  149. if ((p + sizeInBytes) >= end) {
  150. return null;
  151. }
  152. this->index += sizeInBytes;
  153. return (void*) p;
  154. /*
  155. u8* p = this->buffer + this->index;
  156. u32 offset = (u32) alignForward2((u64) p, 64);
  157. //String::memset(p, 0, sizeInBytes);
  158. #pragma clang diagnostic push
  159. #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
  160. if ((void*)(offset + sizeInBytes) <= (this->buffer + this->bufferSizeInBytes)) {
  161. #pragma clang diagnostic pop
  162. void* ptr = &this->buffer[offset];
  163. this->index += offset + sizeInBytes;
  164. String::memset(ptr, 0, sizeInBytes);
  165. return ptr;
  166. }
  167. return null;
  168. */
  169. }
  170. void Arena :: Clear() {
  171. ULE_TYPES_H_FTAG;
  172. this->index = 0;
  173. }
  174. float Arena :: PercentUsed() {
  175. ULE_TYPES_H_FTAG;
  176. return ((float)this->index)/((float)this->bufferSizeInBytes);
  177. }
  178. //================================================================================
  179. struct StackAllocator {
  180. u32 bufferSize;
  181. u32 index;
  182. u8* buffer;
  183. };
  184. struct PoolAllocator {
  185. u8* buffer;
  186. };