1 // Copyright (c) 2015 Sergio Gonzalez. All rights reserved. 2 // License: https://github.com/serge-rgb/milton#license 3 4 #pragma once 5 6 #include "common.h" 7 8 // TODO: out of memory handler. 9 10 #define mlt_malloc(sz) INVALID_CODE_PATH 11 #if DEBUG_MEMORY_USAGE 12 #define mlt_calloc(n, sz, category) calloc_with_debug(n, sz, category, __FILE__, __LINE__) 13 #define mlt_free(ptr, category) free_with_debug(ptr, category); ptr=NULL 14 #define mlt_realloc(ptr, sz, category) realloc_with_debug(ptr, sz, category, __FILE__, __LINE__) 15 #else 16 #define mlt_calloc(n, sz, category) calloc(n, sz) 17 #define mlt_free(ptr, category) do { if (ptr) { free(ptr); ptr = NULL; } else { mlt_assert(!"Freeing null"); } } while(0) 18 #define mlt_realloc(ptr, sz, category) realloc(ptr, sz) 19 #endif 20 21 22 struct Arena 23 { 24 // Memory: 25 size_t size; 26 size_t count; 27 size_t min_block_size; 28 u8* ptr; 29 30 // For pushing/popping 31 Arena* parent; 32 int id; 33 int num_children; 34 }; 35 36 // Stored at the end of the arena. 37 // If the arena expands, its memory block will point to previous memory blocks. 38 struct ArenaFooter 39 { 40 u8* previous_block; 41 size_t previous_size; 42 }; 43 44 // Create a root arena from a memory block. 45 Arena arena_init(size_t min_block_size = 0, void* base = NULL); 46 Arena arena_spawn(Arena* parent, size_t size); 47 void arena_reset(Arena* arena); 48 void arena_reset_noclear(Arena* arena); 49 void arena_free(Arena* arena); 50 51 // ==== Temporary arenas. 52 // Usage: 53 // child = arena_push(my_arena, some_size); 54 // use_temporary_arena(&child.arena); 55 // arena_pop(child); 56 Arena arena_push(Arena* parent, size_t size = 0); 57 void arena_pop(Arena* child); 58 void arena_pop_noclear(Arena* child); 59 60 #define arena_alloc_elem_(arena, T, flags) (T *)arena_alloc_bytes((arena), sizeof(T), flags) 61 #define arena_alloc_array_(arena, count, T, flags) (T *)arena_alloc_bytes((arena), (count) * sizeof(T), flags) 62 #define arena_alloc_elem(arena, T) arena_alloc_elem_(arena, T, Arena_NONE) 63 #define arena_alloc_array(arena, count, T) arena_alloc_array_(arena, count, T, Arena_NONE) 64 #define ARENA_VALIDATE(arena) mlt_assert ((arena)->num_children == 0) 65 #define arena_bootstrap(Type, member, size) (Type*)arena_bootstrap_(size, sizeof(Type), offsetof(Type, member)) 66 67 enum ArenaAllocOpts 68 { 69 Arena_NONE = 0, 70 71 Arena_NOFAIL = 1<<0, 72 }; 73 74 u8* arena_alloc_bytes(Arena* arena, size_t num_bytes, int alloc_flags=Arena_NONE); 75 76 void* arena_bootstrap_(size_t size, size_t obj_size, size_t offset); 77 78 void* calloc_with_debug(size_t n, size_t sz, char* category, char* file, i64 line); 79 void free_with_debug(void* ptr, char* category); 80 void* realloc_with_debug(void* ptr, size_t sz, char* category, char* file, i64 line); 81 void debug_memory_dump_allocations(); 82