Removing heap allocations, Porting to Unix
This commit is contained in:
286
base.cpp
286
base.cpp
@@ -1,7 +1,79 @@
|
||||
#define NOMINMAX
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(__clang__)
|
||||
# define COMPILER_CLANG 1
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# elif defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# else
|
||||
# error Couldnt figure out the platform automatically
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# define COMPILER_MSVC 1
|
||||
# define OS_WINDOWS 1
|
||||
#elif defined(__GNUC__)
|
||||
# define COMPILER_GCC 1
|
||||
# if defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# endif
|
||||
#else
|
||||
# error Couldnt figure out the compiler
|
||||
#endif
|
||||
|
||||
#if defined(OS_MAC)
|
||||
#define OS_UNIX 1
|
||||
#endif
|
||||
#if defined(OS_LINUX)
|
||||
#define OS_UNIX 1
|
||||
#endif
|
||||
|
||||
#if !defined(COMPILER_MSVC)
|
||||
# define COMPILER_MSVC 0
|
||||
#endif
|
||||
#if !defined(COMPILER_GCC)
|
||||
# define COMPILER_GCC 0
|
||||
#endif
|
||||
#if !defined(COMPILER_CLANG)
|
||||
# define COMPILER_CLANG 0
|
||||
#endif
|
||||
#if !defined(OS_WINDOWS)
|
||||
# define OS_WINDOWS 0
|
||||
#endif
|
||||
#if !defined(OS_LINUX)
|
||||
# define OS_LINUX 0
|
||||
#endif
|
||||
#if !defined(OS_MAC)
|
||||
# define OS_MAC 0
|
||||
#endif
|
||||
#if !defined(OS_UNIX)
|
||||
# define OS_UNIX 0
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
#define OS_NAME "Win32"_s
|
||||
#define OS_NAME_LOWER "win32"_s
|
||||
#elif OS_LINUX
|
||||
#define OS_NAME "Linux"_s
|
||||
#define OS_NAME_LOWER "linux"_s
|
||||
#elif OS_MAC
|
||||
#define OS_NAME "Mac"_s
|
||||
#define OS_NAME_LOWER "mac"_s
|
||||
#else
|
||||
#error Couldnt figure out the OS with C macros!
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
#define NOMINMAX
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <windows.h>
|
||||
#define Breakpoint __debugbreak()
|
||||
#define force_inline __forceinline
|
||||
#else
|
||||
#define Breakpoint (*(volatile int *)0 = 0)
|
||||
#define force_inline inline
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
#include <stdint.h>
|
||||
typedef int8_t S8;
|
||||
@@ -16,12 +88,10 @@ typedef S8 B8;
|
||||
typedef S16 B16;
|
||||
typedef S32 B32;
|
||||
typedef S64 B64;
|
||||
typedef U64 SizeU;
|
||||
typedef S64 SizeS;
|
||||
|
||||
typedef float F32;
|
||||
typedef double F64;
|
||||
|
||||
|
||||
#define U64MAX UINT64_MAX
|
||||
#define U32MAX UINT32_MAX
|
||||
#define U16MAX UINT16_MAX
|
||||
@@ -46,13 +116,12 @@ typedef double F64;
|
||||
#define api
|
||||
#define function static
|
||||
#define global static
|
||||
#define force_inline __forceinline
|
||||
#define assert(x) do{if(!(x))__debugbreak();}while(0)
|
||||
#define assert_msg(x,...) assert(x)
|
||||
#define invalid_codepath assert_msg(0, "Invalid codepath")
|
||||
#define invalid_return do{assert_msg(0, "Invalid codepath"); return {};}while(0)
|
||||
#define assert(x) do{if(!(x))Breakpoint;}while(0)
|
||||
#define assert_message(x,...) assert(x)
|
||||
#define invalid_codepath assert_message(0, "Invalid codepath")
|
||||
#define invalid_return do{assert_message(0, "Invalid codepath"); return {};}while(0)
|
||||
#define invalid_default_case default: invalid_codepath
|
||||
#define not_implemented assert_msg(0, "Not implemented")
|
||||
#define not_implemented assert_message(0, "Not implemented")
|
||||
#define unused(x) ((void)x)
|
||||
#define buff_cap(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#define is_flag_set(val,flag) ((val) & (flag))
|
||||
@@ -66,59 +135,6 @@ typedef double F64;
|
||||
#define JOIN(X,Y) JOIN1(X,Y)
|
||||
#define string_expand(x) (int)x.len, x.str
|
||||
|
||||
#if defined(__clang__)
|
||||
# define COMPILER_CLANG 1
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# elif defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# else
|
||||
# error Couldnt figure out the platform automatically
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# define COMPILER_MSVC 1
|
||||
# define OS_WINDOWS 1
|
||||
#elif defined(__GNUC__)
|
||||
# define COMPILER_GCC 1
|
||||
# if defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# endif
|
||||
#else
|
||||
# error Couldnt figure out the compiler
|
||||
#endif
|
||||
|
||||
#if !defined(COMPILER_MSVC)
|
||||
# define COMPILER_MSVC 0
|
||||
#endif
|
||||
#if !defined(COMPILER_GCC)
|
||||
# define COMPILER_GCC 0
|
||||
#endif
|
||||
#if !defined(COMPILER_CLANG)
|
||||
# define COMPILER_CLANG 0
|
||||
#endif
|
||||
#if !defined(OS_WINDOWS)
|
||||
# define OS_WINDOWS 0
|
||||
#endif
|
||||
#if !defined(OS_LINUX)
|
||||
# define OS_LINUX 0
|
||||
#endif
|
||||
#if !defined(OS_MAC)
|
||||
# define OS_MAC 0
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
#define OS_NAME "Win32"_s
|
||||
#define OS_NAME_LOWER "win32"_s
|
||||
#elif OS_LINUX
|
||||
#define OS_NAME "Linux"_s
|
||||
#define OS_NAME_LOWER "linux"_s
|
||||
#elif OS_MAC
|
||||
#define OS_NAME "Mac"_s
|
||||
#define OS_NAME_LOWER "mac"_s
|
||||
#else
|
||||
#error Couldnt figure out the OS with C macros!
|
||||
#endif
|
||||
|
||||
struct String{
|
||||
U8 *str;
|
||||
S64 len;
|
||||
@@ -210,42 +226,42 @@ union Rect2I {
|
||||
//-----------------------------------------------------------------------------
|
||||
// Utilities
|
||||
//-----------------------------------------------------------------------------
|
||||
function SizeU
|
||||
get_align_offset(SizeU size, SizeU align){
|
||||
SizeU mask = align - 1;
|
||||
SizeU val = size & mask;
|
||||
function size_t
|
||||
get_align_offset(size_t size, size_t align){
|
||||
size_t mask = align - 1;
|
||||
size_t val = size & mask;
|
||||
if(val){
|
||||
val = align - val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
function SizeU
|
||||
align_up(SizeU size, SizeU align){
|
||||
SizeU result = size + get_align_offset(size, align);
|
||||
function size_t
|
||||
align_up(size_t size, size_t align){
|
||||
size_t result = size + get_align_offset(size, align);
|
||||
return result;
|
||||
}
|
||||
|
||||
function SizeU
|
||||
align_down(SizeU size, SizeU align){
|
||||
function size_t
|
||||
align_down(size_t size, size_t align){
|
||||
size += 1; // Make sure 8 when align is 8 doesn't get rounded down to 0
|
||||
SizeU result = size - (align - get_align_offset(size, align));
|
||||
size_t result = size - (align - get_align_offset(size, align));
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
memory_copy(void *dst, void *src, SizeU size){
|
||||
memory_copy(void *dst, void *src, size_t size){
|
||||
U8 *d = (U8*)dst;
|
||||
U8 *s = (U8*)src;
|
||||
for(SizeU i = 0; i < size; i++){
|
||||
for(size_t i = 0; i < size; i++){
|
||||
d[i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
memory_zero(void *p, SizeU size){
|
||||
memory_zero(void *p, size_t size){
|
||||
U8 *pp = (U8 *)p;
|
||||
for(SizeU i = 0; i < size; i++)
|
||||
for(size_t i = 0; i < size; i++)
|
||||
pp[i] = 0;
|
||||
}
|
||||
|
||||
@@ -480,47 +496,47 @@ enum Alloc_Flag{
|
||||
};
|
||||
|
||||
struct Allocator;
|
||||
typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, SizeU);
|
||||
typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, size_t);
|
||||
struct Allocator{Allocator_Kind kind; Allocator_Proc *proc; String debug_name;};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory OS
|
||||
//-----------------------------------------------------------------------------
|
||||
struct OS_Memory{
|
||||
SizeU commit, reserve;
|
||||
size_t commit, reserve;
|
||||
U8 *data;
|
||||
};
|
||||
function OS_Memory os_reserve(SizeU size);
|
||||
function B32 os_commit(OS_Memory *m, SizeU size);
|
||||
function OS_Memory os_reserve(size_t size);
|
||||
function B32 os_commit(OS_Memory *m, size_t size);
|
||||
function void os_release(OS_Memory *m);
|
||||
function B32 os_decommit_pos(OS_Memory *m, SizeU pos);
|
||||
function B32 os_decommit_pos(OS_Memory *m, size_t pos);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory arenas
|
||||
//-----------------------------------------------------------------------------
|
||||
global const SizeU default_reserve_size = gib(4);
|
||||
global const SizeU default_alignment = 8;
|
||||
global const SizeU additional_commit_size = mib(1);
|
||||
global const size_t default_reserve_size = gib(4);
|
||||
global const size_t default_alignment = 8;
|
||||
global const size_t additional_commit_size = mib(1);
|
||||
struct Arena:Allocator{
|
||||
OS_Memory memory;
|
||||
SizeU alignment;
|
||||
SizeU len;
|
||||
size_t alignment;
|
||||
size_t len;
|
||||
|
||||
// Personal arena memes so we can compute correct size when resizing
|
||||
// Also a pointer so that we can make sure it didn't change
|
||||
SizeU old_size;
|
||||
size_t old_size;
|
||||
void *debug_prev_pointer;
|
||||
};
|
||||
function void arena_init(Arena *arena, String debug_name);
|
||||
|
||||
function void
|
||||
arena_pop_pos(Arena *arena, SizeU pos){
|
||||
arena_pop_pos(Arena *arena, size_t pos){
|
||||
pos = clamp_top(pos, arena->len);
|
||||
arena->len = pos;
|
||||
}
|
||||
|
||||
function void *
|
||||
arena_pop(Arena *arena, SizeU size){
|
||||
arena_pop(Arena *arena, size_t size){
|
||||
size = clamp_top(size, arena->len);
|
||||
arena->len -= size;
|
||||
return arena->memory.data + arena->len;
|
||||
@@ -537,8 +553,8 @@ arena_clear(Arena *arena){
|
||||
}
|
||||
|
||||
function void *
|
||||
arena_push_size(Arena *a, SizeU size){
|
||||
SizeU generous_size = size + a->alignment;
|
||||
arena_push_size(Arena *a, size_t size){
|
||||
size_t generous_size = size + a->alignment;
|
||||
if(a->len+generous_size>a->memory.commit){
|
||||
if(a->memory.reserve == 0){
|
||||
arena_init(a, "Zero initialized arena"_s);
|
||||
@@ -555,7 +571,7 @@ arena_push_size(Arena *a, SizeU size){
|
||||
}
|
||||
|
||||
force_inline void *
|
||||
arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
||||
arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){
|
||||
Arena *arena = (Arena *)a;
|
||||
switch(kind){
|
||||
case Allocation_Alloc: return arena_push_size(arena, size);
|
||||
@@ -573,7 +589,7 @@ arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, Size
|
||||
}
|
||||
|
||||
force_inline void *
|
||||
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
||||
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){
|
||||
Arena *arena = (Arena *)a;
|
||||
arena->alignment = 1;
|
||||
|
||||
@@ -614,59 +630,6 @@ arena_make_personal(String debug_name){
|
||||
return arena;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OS Heap allocator
|
||||
//-----------------------------------------------------------------------------
|
||||
struct OS_Heap:Allocator{
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
function void *
|
||||
os_heap_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
||||
OS_Heap *heap = (OS_Heap *)a;
|
||||
switch(kind){
|
||||
case Allocation_FreeAll:{
|
||||
invalid_codepath;
|
||||
return 0;
|
||||
}
|
||||
case Allocation_Destroy:{
|
||||
BOOL result = HeapDestroy(heap->handle);
|
||||
assert(result != 0);
|
||||
heap->handle = 0;
|
||||
heap->proc = 0;
|
||||
return 0;
|
||||
}
|
||||
case Allocation_Free:{
|
||||
BOOL result = HeapFree(heap->handle, 0, old_pointer);
|
||||
assert(result != 0);
|
||||
return 0;
|
||||
}
|
||||
case Allocation_Alloc:{
|
||||
void *result = HeapAlloc(heap->handle, 0, size);
|
||||
assert(result);
|
||||
return result;
|
||||
}
|
||||
case Allocation_Resize:{
|
||||
void *result = HeapReAlloc(heap->handle, 0, old_pointer, size);
|
||||
assert(result);
|
||||
return result;
|
||||
}
|
||||
default: invalid_codepath;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function OS_Heap // max_size == 0 == growing heap
|
||||
win32_os_heap_create(B32 multithreaded, SizeU initial_size, SizeU max_size, String debug_name){
|
||||
OS_Heap result = {};
|
||||
result.debug_name = debug_name;
|
||||
result.proc = os_heap_allocator_proc;
|
||||
result.kind = Allocator_OSHeap;
|
||||
result.handle = HeapCreate(multithreaded ? 0 : HEAP_NO_SERIALIZE, initial_size, max_size);
|
||||
assert(result.handle);
|
||||
return result;
|
||||
}
|
||||
|
||||
enum Log_Kind{Log_Kind_Normal, Log_Kind_Error, Log_Kind_Trace};
|
||||
typedef void Log_Proc(Log_Kind kind, String string, char *file, int line);
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -684,7 +647,6 @@ struct Thread_Ctx{
|
||||
|
||||
thread_local Thread_Ctx thread_ctx;
|
||||
global Arena pernament_arena;
|
||||
global OS_Heap os_process_heap;
|
||||
|
||||
#define REPORT_ALLOCATIONS 0
|
||||
#define report_file_and_line() report__file_and_line(__FILE__, __LINE__)
|
||||
@@ -698,7 +660,7 @@ report__file_and_line(const char *file, int line){
|
||||
// Implicit scratch stack
|
||||
//-----------------------------------------------------------------------------
|
||||
struct Scratch{
|
||||
SizeU saved_pos;
|
||||
size_t saved_pos;
|
||||
Arena *arena;
|
||||
|
||||
Scratch(Allocator *conflict = 0){
|
||||
@@ -749,7 +711,7 @@ struct Scoped_Allocator{
|
||||
#define exp_destroy(a) (report_file_and_line(), exp__destroy(a))
|
||||
|
||||
force_inline void *
|
||||
exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){
|
||||
exp__alloc(Allocator *a, size_t size, Alloc_Flag flag = AF_None){
|
||||
#if REPORT_ALLOCATIONS
|
||||
printf("Alloc(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
|
||||
#endif
|
||||
@@ -759,7 +721,7 @@ exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){
|
||||
return result;
|
||||
}
|
||||
force_inline void *
|
||||
exp__resize(Allocator *a, void *pointer, SizeU size){
|
||||
exp__resize(Allocator *a, void *pointer, size_t size){
|
||||
#if REPORT_ALLOCATIONS
|
||||
printf("Resize(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
|
||||
#endif
|
||||
@@ -801,10 +763,6 @@ thread_ctx_init(){
|
||||
arena_init(thread_ctx.scratch, "Scratch1"_s);
|
||||
arena_init(thread_ctx.scratch+1, "Scratch2"_s);
|
||||
arena_init(&pernament_arena, "Pernament Arena"_s);
|
||||
os_process_heap.proc = os_heap_allocator_proc;
|
||||
os_process_heap.handle = GetProcessHeap();
|
||||
os_process_heap.debug_name = "Win32 Process Heap"_s;
|
||||
os_process_heap.kind = Allocator_OSHeap;
|
||||
}
|
||||
|
||||
|
||||
@@ -847,7 +805,7 @@ struct Array{
|
||||
|
||||
S64 get_index(T *item){
|
||||
assert((data <= item) && ((data + len) > item));
|
||||
SizeU offset = item - data;
|
||||
size_t offset = item - data;
|
||||
return (S64)offset;
|
||||
}
|
||||
|
||||
@@ -1145,12 +1103,12 @@ function void
|
||||
map_test(){
|
||||
Scratch scratch;
|
||||
Map map = {scratch};
|
||||
const SizeU size = 1025;
|
||||
for(SizeU i = 1; i < size; i++){
|
||||
const size_t size = 1025;
|
||||
for(size_t i = 1; i < size; i++){
|
||||
map_insert(&map, i, (void *)i);
|
||||
}
|
||||
for(SizeU i = 1; i < size; i++){
|
||||
SizeU val = (SizeU)map_get(&map, i);
|
||||
for(size_t i = 1; i < size; i++){
|
||||
size_t val = (size_t)map_get(&map, i);
|
||||
assert(val == i);
|
||||
}
|
||||
}
|
||||
@@ -1208,7 +1166,7 @@ test_intern_table(){
|
||||
}
|
||||
|
||||
function Arena
|
||||
arena_sub(Allocator *base, SizeU size, String debug_name) {
|
||||
arena_sub(Allocator *base, size_t size, String debug_name) {
|
||||
Arena result = {};
|
||||
result.memory.data = (U8 *)exp_alloc(base, size);
|
||||
result.memory.commit = size;
|
||||
@@ -1443,7 +1401,7 @@ T pop(List<T> *list){
|
||||
template<class T>
|
||||
T *merge(Arena *arena, List<T> *list){
|
||||
int len = length(list);
|
||||
T *result = push_array(arena, T, len);
|
||||
T *result = exp_alloc_array(arena, T, len);
|
||||
|
||||
int i = 0;
|
||||
For_Linked_List(list->first){
|
||||
|
||||
Reference in New Issue
Block a user