Explicit allocators
This commit is contained in:
parent
bf32265517
commit
ea37ceb3bd
12 changed files with 172 additions and 221 deletions
9
entry.c
9
entry.c
|
@ -18,9 +18,9 @@ int start(int argc, char **argv) {
|
|||
|
||||
window.clear_color = hex_to_rgba(0x2a2d3aff);
|
||||
|
||||
Gfx_Image *bush_image = load_image_from_disk(fixed_string("berry_bush.png"));
|
||||
Gfx_Image *bush_image = load_image_from_disk(fixed_string("berry_bush.png"), get_heap_allocator());
|
||||
assert(bush_image, "Failed loading berry_bush.png");
|
||||
Gfx_Image *hammer_image = load_image_from_disk(fixed_string("hammer.png"));
|
||||
Gfx_Image *hammer_image = load_image_from_disk(fixed_string("hammer.png"), get_heap_allocator());
|
||||
assert(hammer_image, "Failed loading hammer.png");
|
||||
|
||||
seed_for_random = os_get_current_cycle_count();
|
||||
|
@ -33,7 +33,6 @@ int start(int argc, char **argv) {
|
|||
float64 last_time = os_get_current_time_in_seconds();
|
||||
while (!window.should_close) {
|
||||
reset_temporary_storage();
|
||||
context.allocator = temp;
|
||||
|
||||
float64 now = os_get_current_time_in_seconds();
|
||||
float64 delta = now - last_time;
|
||||
|
@ -58,11 +57,9 @@ int start(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (is_key_just_released('Q')) {
|
||||
push_allocator(get_heap_allocator());
|
||||
delete_image(bush_image);
|
||||
bush_image = load_image_from_disk(fixed_string("berry_bush.png"));
|
||||
bush_image = load_image_from_disk(fixed_string("berry_bush.png"), get_heap_allocator());
|
||||
assert(bush_image, "Failed loading berry_bush.png");
|
||||
pop_allocator();
|
||||
}
|
||||
|
||||
const float32 cam_move_speed = 4.0;
|
||||
|
|
|
@ -101,11 +101,12 @@ void printf(const char* fmt, ...);
|
|||
|
||||
|
||||
#define FIRST_ARG(arg1, ...) arg1
|
||||
#define SECOND_ARG(arg1, arg2, ...) arg2
|
||||
#define print(...) _Generic((FIRST_ARG(__VA_ARGS__)), \
|
||||
string: prints, \
|
||||
default: printf \
|
||||
)(__VA_ARGS__)
|
||||
#define sprint(...) _Generic((FIRST_ARG(__VA_ARGS__)), \
|
||||
#define sprint(...) _Generic((SECOND_ARG(__VA_ARGS__)), \
|
||||
string: sprints, \
|
||||
default: sprintf \
|
||||
)(__VA_ARGS__)
|
||||
|
@ -125,7 +126,7 @@ typedef enum Allocator_Message {
|
|||
ALLOCATOR_DEALLOCATE,
|
||||
ALLOCATOR_REALLOCATE,
|
||||
} Allocator_Message;
|
||||
typedef void*(*Allocator_Proc)(u64, void*, Allocator_Message);
|
||||
typedef void*(*Allocator_Proc)(u64, void*, Allocator_Message, void*);
|
||||
|
||||
typedef enum Log_Level {
|
||||
LOG_ERROR,
|
||||
|
@ -142,7 +143,6 @@ typedef struct Allocator {
|
|||
} Allocator;
|
||||
|
||||
typedef struct Context {
|
||||
Allocator allocator;
|
||||
void *logger; // void(*Logger_Proc)(Log_Level level, string fmt, ...)
|
||||
|
||||
CONTEXT_EXTRA extra;
|
||||
|
@ -154,8 +154,14 @@ thread_local Context context;
|
|||
thread_local Context context_stack[CONTEXT_STACK_MAX];
|
||||
thread_local u64 num_contexts = 0;
|
||||
|
||||
void* alloc(u64 size) { return context.allocator.proc(size, NULL, ALLOCATOR_ALLOCATE); }
|
||||
void dealloc(void *p) { context.allocator.proc(0, p, ALLOCATOR_DEALLOCATE); }
|
||||
forward_global thread_local Allocator temp;
|
||||
|
||||
void* alloc(Allocator allocator, u64 size) {
|
||||
return allocator.proc(size, 0, ALLOCATOR_ALLOCATE, allocator.data);
|
||||
}
|
||||
void dealloc(Allocator allocator, void *p) {
|
||||
allocator.proc(0, p, ALLOCATOR_DEALLOCATE, allocator.data);
|
||||
}
|
||||
|
||||
void push_context(Context c) {
|
||||
assert(num_contexts < CONTEXT_STACK_MAX, "Context stack overflow");
|
||||
|
@ -170,11 +176,4 @@ void pop_context() {
|
|||
context = context_stack[num_contexts];
|
||||
}
|
||||
|
||||
void push_allocator(Allocator a) {
|
||||
Context c = context;
|
||||
c.allocator = a;
|
||||
push_context(c);
|
||||
}
|
||||
void pop_allocator() { pop_context(); }
|
||||
|
||||
|
||||
|
|
|
@ -185,16 +185,17 @@ Draw_Quad *draw_image_xform(Gfx_Image *image, Matrix4 xform, Vector2 size, Vecto
|
|||
#define COLOR_WHITE ((Vector4){1.0, 1.0, 1.0, 1.0})
|
||||
#define COLOR_BLACK ((Vector4){0.0, 0.0, 0.0, 1.0})
|
||||
|
||||
// context.allocator
|
||||
Gfx_Image *load_image_from_disk(string path) {
|
||||
Gfx_Image *load_image_from_disk(string path, Allocator allocator) {
|
||||
string png;
|
||||
bool ok = os_read_entire_file(path, &png);
|
||||
bool ok = os_read_entire_file(path, &png, allocator);
|
||||
if (!ok) return 0;
|
||||
|
||||
Gfx_Image *image = alloc(sizeof(Gfx_Image));
|
||||
Gfx_Image *image = alloc(allocator, sizeof(Gfx_Image));
|
||||
|
||||
// This is fucking terrible I gotta write my own decoder
|
||||
|
||||
lodepng_allocator = allocator;
|
||||
|
||||
LodePNGState state;
|
||||
lodepng_state_init(&state);
|
||||
u32 error = lodepng_inspect(&image->width, &image->height, &state, png.data, png.count);
|
||||
|
@ -214,7 +215,7 @@ Gfx_Image *load_image_from_disk(string path) {
|
|||
|
||||
lodepng_state_cleanup(&state);
|
||||
|
||||
dealloc_string(png);
|
||||
dealloc_string(allocator, png);
|
||||
|
||||
if (error) {
|
||||
return 0;
|
||||
|
@ -222,7 +223,7 @@ Gfx_Image *load_image_from_disk(string path) {
|
|||
|
||||
// We need to flip the image
|
||||
u32 row_bytes = image->width * 4; // #Magicvalue assuming 4 bytes
|
||||
u8* temp_row = (u8*)alloc(row_bytes);
|
||||
u8* temp_row = (u8*)alloc(temp, row_bytes);
|
||||
for (u32 i = 0; i < image->height / 2; i++) {
|
||||
u8* top_row = image->data + i * row_bytes;
|
||||
u8* bottom_row = image->data + (image->height - i - 1) * row_bytes;
|
||||
|
@ -232,17 +233,18 @@ Gfx_Image *load_image_from_disk(string path) {
|
|||
memcpy(top_row, bottom_row, row_bytes);
|
||||
memcpy(bottom_row, temp_row, row_bytes);
|
||||
}
|
||||
dealloc(temp_row);
|
||||
|
||||
image->gfx_handle = GFX_INVALID_HANDLE; // This is handled in gfx
|
||||
|
||||
image->allocator = allocator;
|
||||
|
||||
return image;
|
||||
}
|
||||
void delete_image(Gfx_Image *image) {
|
||||
dealloc(image->data);
|
||||
dealloc(image->allocator, image->data);
|
||||
image->width = 0;
|
||||
image->height = 0;
|
||||
draw_frame.garbage_stack[draw_frame.garbage_stack_count] = image->gfx_handle;
|
||||
draw_frame.garbage_stack_count += 1;
|
||||
dealloc(image);
|
||||
dealloc(image->allocator, image);
|
||||
}
|
|
@ -313,7 +313,7 @@ void gfx_init() {
|
|||
#if OOGABOOGA_DEV
|
||||
|
||||
string source;
|
||||
bool source_ok = os_read_entire_file(fxstr("oogabooga/dev/d3d11_image_shader.hlsl"), &source);
|
||||
bool source_ok = os_read_entire_file(fxstr("oogabooga/dev/d3d11_image_shader.hlsl"), &source, get_heap_allocator()); // #Leak
|
||||
assert(source_ok, "Could not open d3d11_image_shader source");
|
||||
|
||||
// Compile vertex shader
|
||||
|
|
|
@ -33,5 +33,6 @@ typedef struct Gfx_Image {
|
|||
u32 width, height;
|
||||
u8 *data;
|
||||
Gfx_Handle gfx_handle;
|
||||
Allocator allocator;
|
||||
} Gfx_Image;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ u64 program_memory_size = 0;
|
|||
u8 init_memory_arena[INIT_MEMORY_SIZE];
|
||||
u8 *init_memory_head = init_memory_arena;
|
||||
|
||||
void* initialization_allocator_proc(u64 size, void *p, Allocator_Message message) {
|
||||
void* initialization_allocator_proc(u64 size, void *p, Allocator_Message message, void *data) {
|
||||
switch (message) {
|
||||
case ALLOCATOR_ALLOCATE: {
|
||||
p = init_memory_head;
|
||||
|
@ -35,6 +35,12 @@ void* initialization_allocator_proc(u64 size, void *p, Allocator_Message message
|
|||
return 0;
|
||||
}
|
||||
|
||||
Allocator get_initialization_allocator() {
|
||||
Allocator a;
|
||||
a.proc = initialization_allocator_proc;
|
||||
return a;
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
// Basic general heap allocator, free list
|
||||
|
@ -206,7 +212,7 @@ void heap_init() {
|
|||
if (heap_initted) return;
|
||||
heap_initted = true;
|
||||
heap_head = make_heap_block(0, DEFAULT_HEAP_BLOCK_SIZE);
|
||||
heap_lock = os_make_spinlock();
|
||||
heap_lock = os_make_spinlock(get_initialization_allocator());
|
||||
}
|
||||
|
||||
void *heap_alloc(u64 size) {
|
||||
|
@ -376,7 +382,7 @@ void heap_dealloc(void *p) {
|
|||
os_spinlock_unlock(heap_lock);
|
||||
}
|
||||
|
||||
void* heap_allocator_proc(u64 size, void *p, Allocator_Message message) {
|
||||
void* heap_allocator_proc(u64 size, void *p, Allocator_Message message, void* data) {
|
||||
switch (message) {
|
||||
case ALLOCATOR_ALLOCATE: {
|
||||
return heap_alloc(size);
|
||||
|
@ -421,7 +427,7 @@ Allocator get_heap_allocator() {
|
|||
#endif
|
||||
|
||||
void* talloc(u64);
|
||||
void* temp_allocator_proc(u64 size, void *p, Allocator_Message message);
|
||||
void* temp_allocator_proc(u64 size, void *p, Allocator_Message message, void*);
|
||||
|
||||
thread_local void * temporary_storage = 0;
|
||||
thread_local bool temporary_storage_initted = false;
|
||||
|
@ -430,7 +436,7 @@ thread_local bool has_warned_temporary_storage_overflow = false;
|
|||
thread_local Allocator temp;
|
||||
|
||||
|
||||
void* temp_allocator_proc(u64 size, void *p, Allocator_Message message) {
|
||||
void* temp_allocator_proc(u64 size, void *p, Allocator_Message message, void* data) {
|
||||
switch (message) {
|
||||
case ALLOCATOR_ALLOCATE: {
|
||||
return talloc(size);
|
||||
|
@ -457,6 +463,8 @@ void temporary_storage_init() {
|
|||
temp.data = 0;
|
||||
|
||||
temporary_storage_initted = true;
|
||||
|
||||
temp.proc = temp_allocator_proc;
|
||||
}
|
||||
|
||||
void* talloc(u64 size) {
|
||||
|
@ -487,8 +495,3 @@ void reset_temporary_storage() {
|
|||
has_warned_temporary_storage_overflow = true;
|
||||
}
|
||||
|
||||
// So we can do this in code included before this.
|
||||
void push_temp_allocator() {
|
||||
if (!temporary_storage_initted) temporary_storage_init();
|
||||
push_allocator(temp);
|
||||
}
|
|
@ -32,16 +32,22 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
Allocator get_heap_allocator();
|
||||
|
||||
// Custom allocators for lodepng
|
||||
Allocator lodepng_allocator = {0};
|
||||
void* lodepng_malloc(size_t size) {
|
||||
return context.allocator.proc((u64)size, 0, ALLOCATOR_ALLOCATE);
|
||||
if (lodepng_allocator.proc) return alloc(lodepng_allocator, size);
|
||||
return alloc(get_heap_allocator(), size);
|
||||
}
|
||||
void* lodepng_realloc(void* ptr, size_t new_size) {
|
||||
return context.allocator.proc((u64)new_size, ptr, ALLOCATOR_REALLOCATE);
|
||||
if (lodepng_allocator.proc) return lodepng_allocator.proc(new_size, ptr, ALLOCATOR_REALLOCATE, lodepng_allocator.data);
|
||||
return get_heap_allocator().proc(new_size, ptr, ALLOCATOR_REALLOCATE, get_heap_allocator().data);
|
||||
}
|
||||
void lodepng_free(void* ptr) {
|
||||
if (!ptr) return;
|
||||
context.allocator.proc(0, ptr, ALLOCATOR_DEALLOCATE);
|
||||
if (lodepng_allocator.proc) dealloc(lodepng_allocator, ptr);
|
||||
else dealloc(get_heap_allocator(), ptr);
|
||||
}
|
||||
#define LODEPNG_NO_COMPILE_ALLOCATORS
|
||||
//#define LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
|
||||
|
@ -161,10 +167,11 @@ void lodepng_free(void* ptr) {
|
|||
|
||||
void oogabooga_init(u64 program_memory_size) {
|
||||
context.logger = default_logger;
|
||||
temp = get_initialization_allocator();
|
||||
os_init(program_memory_size);
|
||||
gfx_init();
|
||||
heap_init();
|
||||
temporary_storage_init();
|
||||
gfx_init();
|
||||
}
|
||||
|
||||
#ifndef INITIAL_PROGRAM_MEMORY_SIZE
|
||||
|
@ -178,7 +185,6 @@ void oogabooga_init(u64 program_memory_size) {
|
|||
int ENTRY_PROC(int argc, char **argv);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
context.allocator.proc = initialization_allocator_proc;
|
||||
oogabooga_init(INITIAL_PROGRAM_MEMORY_SIZE);
|
||||
printf("Ooga booga program started\n");
|
||||
|
||||
|
|
|
@ -162,7 +162,6 @@ void os_init(u64 program_memory_size) {
|
|||
|
||||
|
||||
heap_init();
|
||||
context.allocator = get_heap_allocator();
|
||||
|
||||
os.crt = os_load_dynamic_library(const_string("msvcrt.dll"));
|
||||
assert(os.crt != 0, "Could not load win32 crt library. Might be compiled with non-msvc? #Incomplete #Portability");
|
||||
|
@ -308,8 +307,8 @@ DWORD WINAPI win32_thread_invoker(LPVOID param) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Thread* os_make_thread(Thread_Proc proc) {
|
||||
Thread *t = (Thread*)alloc(sizeof(Thread));
|
||||
Thread* os_make_thread(Thread_Proc proc, Allocator allocator) {
|
||||
Thread *t = (Thread*)alloc(allocator, sizeof(Thread));
|
||||
t->id = 0; // This is set when we start it
|
||||
t->proc = proc;
|
||||
t->initial_context = context;
|
||||
|
@ -365,8 +364,9 @@ void os_unlock_mutex(Mutex_Handle m) {
|
|||
///
|
||||
// Spinlock "primitive"
|
||||
|
||||
Spinlock *os_make_spinlock() {
|
||||
Spinlock *l = cast(Spinlock*)alloc(sizeof(Spinlock));
|
||||
Spinlock *os_make_spinlock(Allocator allocator) {
|
||||
// #Memory #Cleanup do we need to heap allocate this ?
|
||||
Spinlock *l = cast(Spinlock*)alloc(allocator, sizeof(Spinlock));
|
||||
l->locked = false;
|
||||
return l;
|
||||
}
|
||||
|
@ -490,15 +490,14 @@ void os_write_string_to_stdout(string s) {
|
|||
WriteFile(win32_stdout, s.data, s.count, 0, NULL);
|
||||
}
|
||||
|
||||
// context.allocator
|
||||
u16 *win32_fixed_utf8_to_null_terminated_wide(string utf8) {
|
||||
u16 *win32_fixed_utf8_to_null_terminated_wide(string utf8, Allocator allocator) {
|
||||
u64 utf16_length = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)utf8.data, (int)utf8.count, 0, 0);
|
||||
|
||||
u16 *utf16_str = (u16 *)alloc((utf16_length + 1) * sizeof(u16));
|
||||
u16 *utf16_str = (u16 *)alloc(allocator, (utf16_length + 1) * sizeof(u16));
|
||||
|
||||
int result = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)utf8.data, (int)utf8.count, utf16_str, utf16_length);
|
||||
if (result == 0) {
|
||||
dealloc(utf16_str);
|
||||
dealloc(allocator, utf16_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -507,19 +506,16 @@ u16 *win32_fixed_utf8_to_null_terminated_wide(string utf8) {
|
|||
return utf16_str;
|
||||
}
|
||||
u16 *temp_win32_fixed_utf8_to_null_terminated_wide(string utf8) {
|
||||
push_temp_allocator();
|
||||
u16 *result = win32_fixed_utf8_to_null_terminated_wide(utf8);
|
||||
pop_allocator();
|
||||
return result;
|
||||
return win32_fixed_utf8_to_null_terminated_wide(utf8, temp);
|
||||
}
|
||||
string win32_null_terminated_wide_to_fixed_utf8(const u16 *utf16) {
|
||||
string win32_null_terminated_wide_to_fixed_utf8(const u16 *utf16, Allocator allocator) {
|
||||
u64 utf8_length = WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)utf16, -1, 0, 0, 0, 0);
|
||||
|
||||
u8 *utf8_str = (u8 *)alloc(utf8_length * sizeof(u8));
|
||||
u8 *utf8_str = (u8 *)alloc(allocator, utf8_length * sizeof(u8));
|
||||
|
||||
int result = WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)utf16, -1, (LPSTR)utf8_str, (int)utf8_length, 0, 0);
|
||||
if (result == 0) {
|
||||
dealloc(utf8_str);
|
||||
dealloc(allocator, utf8_str);
|
||||
return (string){0, 0};
|
||||
}
|
||||
|
||||
|
@ -531,10 +527,7 @@ string win32_null_terminated_wide_to_fixed_utf8(const u16 *utf16) {
|
|||
}
|
||||
|
||||
string temp_win32_null_terminated_wide_to_fixed_utf8(const u16 *utf16) {
|
||||
push_temp_allocator();
|
||||
string result = win32_null_terminated_wide_to_fixed_utf8(utf16);
|
||||
pop_allocator();
|
||||
return result;
|
||||
return win32_null_terminated_wide_to_fixed_utf8(utf16, temp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -600,19 +593,19 @@ bool os_write_entire_file(string path, string data) {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool os_read_entire_file_handle(File f, string *result) {
|
||||
bool os_read_entire_file_handle(File f, string *result, Allocator allocator) {
|
||||
LARGE_INTEGER file_size;
|
||||
if (!GetFileSizeEx(f, &file_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 actual_read = 0;
|
||||
result->data = (u8*)alloc(file_size.QuadPart);
|
||||
result->data = (u8*)alloc(allocator, file_size.QuadPart);
|
||||
result->count = file_size.QuadPart;
|
||||
|
||||
bool ok = os_file_read(f, result->data, file_size.QuadPart, &actual_read);
|
||||
if (!ok) {
|
||||
dealloc(result->data);
|
||||
dealloc(allocator, result->data);
|
||||
result->data = 0;
|
||||
return false;
|
||||
}
|
||||
|
@ -620,12 +613,12 @@ bool os_read_entire_file_handle(File f, string *result) {
|
|||
return actual_read == file_size.QuadPart;
|
||||
}
|
||||
|
||||
bool os_read_entire_file(string path, string *result) {
|
||||
bool os_read_entire_file(string path, string *result, Allocator allocator) {
|
||||
File file = os_file_open(path, O_READ);
|
||||
if (file == OS_INVALID_FILE) {
|
||||
return false;
|
||||
}
|
||||
bool res = os_read_entire_file_handle(file, result);
|
||||
bool res = os_read_entire_file_handle(file, result, allocator);
|
||||
os_file_close(file);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ typedef struct Thread {
|
|||
|
||||
///
|
||||
// Thread primitive
|
||||
Thread* os_make_thread(Thread_Proc proc);
|
||||
Thread* os_make_thread(Thread_Proc proc, Allocator allocator);
|
||||
void os_start_thread(Thread* t);
|
||||
void os_join_thread(Thread* t);
|
||||
|
||||
|
@ -145,7 +145,7 @@ void os_unlock_mutex(Mutex_Handle m);
|
|||
typedef struct Spinlock {
|
||||
bool locked;
|
||||
} Spinlock;
|
||||
Spinlock *os_make_spinlock();
|
||||
Spinlock *os_make_spinlock(Allocator allocator);
|
||||
void os_spinlock_lock(Spinlock* l);
|
||||
void os_spinlock_unlock(Spinlock* l);
|
||||
|
||||
|
@ -210,8 +210,8 @@ bool os_file_read(File f, void* buffer, u64 bytes_to_read, u64 *actual_read_byte
|
|||
|
||||
bool os_write_entire_file_handle(File f, string data);
|
||||
bool os_write_entire_file(string path, string data);
|
||||
bool os_read_entire_file_handle(File f, string *result);
|
||||
bool os_read_entire_file(string path, string *result);
|
||||
bool os_read_entire_file_handle(File f, string *result, Allocator allocator);
|
||||
bool os_read_entire_file(string path, string *result, Allocator allocator);
|
||||
|
||||
bool os_is_file(string path);
|
||||
bool os_is_directory(string path);
|
||||
|
|
|
@ -1,41 +1,6 @@
|
|||
|
||||
/*
|
||||
Usage:
|
||||
|
||||
// We need to use macro const_string to convert literal to string
|
||||
string fmt = const_string("Pointer address: 0x%x");
|
||||
print(fmt, cast(u64)&a); // Print to stdout
|
||||
|
||||
// Format a string and allocate with context.allocator
|
||||
string a = sprint("Hello, %cs!\n", "balls"); // %cs for char*
|
||||
|
||||
string balls = const_string("balls");
|
||||
// tprint for temporary allocation
|
||||
string b = tprint("Hello, %s!\n", balls); // %s for string
|
||||
|
||||
// Allocate a new string of length 12 (with context allocator)
|
||||
string c = alloc_string(12);
|
||||
dealloc_string(c);
|
||||
|
||||
// We can use raw char* for format with printf/sprintf/tprintf
|
||||
printf("Hello, %!\n", balls);
|
||||
|
||||
// concatenation
|
||||
string concatenated = string_concat(a, b);
|
||||
|
||||
// Use temporary memory to make a null-terminated copy of fixed-length string
|
||||
char* cstring = temp_convert_to_null_terminated_string(balls);
|
||||
|
||||
// To convert a cstring to string (using same memory)
|
||||
string s;
|
||||
s.data = (u8*)cstring;
|
||||
s.count = strlen(cstring);
|
||||
|
||||
// String matching
|
||||
bool match = strings_match(a, b);
|
||||
|
||||
// View into "Hello, balls!\n" from index 7 with a count of 5; "balls"
|
||||
string balls2 = string_view(a, 7, 5);
|
||||
|
||||
|
||||
*/
|
||||
|
@ -48,8 +13,6 @@ typedef struct string {
|
|||
u8 *data;
|
||||
} string;
|
||||
|
||||
void push_temp_allocator();
|
||||
|
||||
// Not sure what to call this lol
|
||||
#define fxstr fixed_string
|
||||
#define fixed_string const_string
|
||||
|
@ -65,43 +28,37 @@ inline u64 length_of_null_terminated_string(const char* cstring) {
|
|||
return len;
|
||||
}
|
||||
|
||||
string alloc_string(u64 count) {
|
||||
string alloc_string(Allocator allocator, u64 count) {
|
||||
string s;
|
||||
s.count = count;
|
||||
s.data = cast(u8*)alloc(count);
|
||||
s.data = cast(u8*)alloc(allocator, count);
|
||||
return s;
|
||||
}
|
||||
void dealloc_string(string s) {
|
||||
dealloc(s.data);
|
||||
void dealloc_string(Allocator allocator, string s) {
|
||||
dealloc(allocator, s.data);
|
||||
}
|
||||
string talloc_string(u64 count) {
|
||||
push_temp_allocator();
|
||||
string s = alloc_string(count);
|
||||
pop_allocator();
|
||||
string s = alloc_string(temp, count);
|
||||
return s;
|
||||
}
|
||||
|
||||
// context.allocator !
|
||||
string string_concat(const string left, const string right) {
|
||||
string string_concat(const string left, const string right, Allocator allocator) {
|
||||
string result;
|
||||
result.count = left.count + right.count;
|
||||
result.data = cast(u8*)alloc(result.count);
|
||||
result.data = cast(u8*)alloc(allocator, result.count);
|
||||
memcpy(result.data, left.data, left.count);
|
||||
memcpy(result.data+left.count, right.data, right.count);
|
||||
return result;
|
||||
}
|
||||
// context.allocator !
|
||||
char *convert_to_null_terminated_string(const string s) {
|
||||
char *cstring = cast(char*)alloc(s.count+1);
|
||||
char *convert_to_null_terminated_string(const string s, Allocator allocator) {
|
||||
char *cstring = cast(char*)alloc(allocator, s.count+1);
|
||||
memcpy(cstring, s.data, s.count);
|
||||
cstring[s.count] = 0;
|
||||
return cstring;
|
||||
}
|
||||
|
||||
char *temp_convert_to_null_terminated_string(const string s) {
|
||||
push_temp_allocator();
|
||||
char *c = convert_to_null_terminated_string(s);
|
||||
pop_allocator();
|
||||
char *c = convert_to_null_terminated_string(s, temp);
|
||||
return c;
|
||||
}
|
||||
bool strings_match(string a, string b) {
|
||||
|
|
|
@ -102,24 +102,24 @@ string sprint_va_list_to_buffer(const string fmt, va_list args, void* buffer, u6
|
|||
char* fmt_cstring = temp_convert_to_null_terminated_string(fmt);
|
||||
return sprint_null_terminated_string_va_list_to_buffer(fmt_cstring, args, buffer, count);
|
||||
}
|
||||
// context.allocator
|
||||
string sprint_va_list(const string fmt, va_list args) {
|
||||
|
||||
string sprint_va_list(Allocator allocator, const string fmt, va_list args) {
|
||||
|
||||
char* fmt_cstring = temp_convert_to_null_terminated_string(fmt);
|
||||
u64 count = format_string_to_buffer(NULL, 0, fmt_cstring, args) + 1;
|
||||
|
||||
char* buffer = NULL;
|
||||
|
||||
buffer = (char*)alloc(count);
|
||||
buffer = (char*)alloc(allocator, count);
|
||||
|
||||
return sprint_null_terminated_string_va_list_to_buffer(fmt_cstring, args, buffer, count);
|
||||
}
|
||||
|
||||
// context.allocator
|
||||
string sprints(const string fmt, ...) {
|
||||
|
||||
string sprints(Allocator allocator, const string fmt, ...) {
|
||||
va_list args = 0;
|
||||
va_start(args, fmt);
|
||||
string s = sprint_va_list(fmt, args);
|
||||
string s = sprint_va_list(allocator, fmt, args);
|
||||
va_end(args);
|
||||
return s;
|
||||
}
|
||||
|
@ -128,22 +128,20 @@ string sprints(const string fmt, ...) {
|
|||
string tprints(const string fmt, ...) {
|
||||
va_list args = 0;
|
||||
va_start(args, fmt);
|
||||
push_temp_allocator();
|
||||
string s = sprint_va_list(fmt, args);
|
||||
pop_allocator();
|
||||
string s = sprint_va_list(temp, fmt, args);
|
||||
va_end(args);
|
||||
return s;
|
||||
}
|
||||
|
||||
// context.allocator
|
||||
string sprintf(const char *fmt, ...) {
|
||||
|
||||
string sprintf(Allocator allocator, const char *fmt, ...) {
|
||||
string sfmt;
|
||||
sfmt.data = cast(u8*)fmt;
|
||||
sfmt.count = strlen(fmt);
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
string s = sprint_va_list(sfmt, args);
|
||||
string s = sprint_va_list(allocator, sfmt, args);
|
||||
va_end(args);
|
||||
|
||||
return s;
|
||||
|
@ -156,22 +154,12 @@ string tprintf(const char *fmt, ...) {
|
|||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
push_temp_allocator();
|
||||
string s = sprint_va_list(sfmt, args);
|
||||
pop_allocator();
|
||||
string s = sprint_va_list(temp, sfmt, args);
|
||||
va_end(args);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// context.allocator (alloc & dealloc)
|
||||
void print_va_list(const string fmt, va_list args) {
|
||||
string s = sprint_va_list(fmt, args);
|
||||
os_write_string_to_stdout(s);
|
||||
dealloc(s.data);
|
||||
}
|
||||
|
||||
// print for 'string' and printf for 'char*'
|
||||
|
||||
#define PRINT_BUFFER_SIZE 4096
|
||||
|
@ -203,14 +191,14 @@ void print_va_list_buffered(const string fmt, va_list args) {
|
|||
}
|
||||
|
||||
|
||||
// context.allocator (alloc & dealloc)
|
||||
|
||||
void prints(const string fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
print_va_list_buffered(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
// context.allocator (alloc & dealloc)
|
||||
|
||||
void printf(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
|
|
@ -30,10 +30,13 @@ void log_heap() {
|
|||
}
|
||||
|
||||
void test_allocator(bool do_log_heap) {
|
||||
|
||||
Allocator heap = get_heap_allocator();
|
||||
|
||||
// Basic allocation and free
|
||||
int* a = (int*)alloc(sizeof(int));
|
||||
int* b = (int*)alloc(sizeof(int));
|
||||
int* c = (int*)alloc(sizeof(int));
|
||||
int* a = (int*)alloc(heap, sizeof(int));
|
||||
int* b = (int*)alloc(heap, sizeof(int));
|
||||
int* c = (int*)alloc(heap, sizeof(int));
|
||||
|
||||
*a = 69;
|
||||
*b = 420;
|
||||
|
@ -51,41 +54,41 @@ void test_allocator(bool do_log_heap) {
|
|||
assert(*c == 1337, "Test failed: Memory corrupted");
|
||||
|
||||
// Allocate and free large block
|
||||
void* large_block = alloc(1024 * 1024 * 100);
|
||||
dealloc(large_block);
|
||||
void* large_block = alloc(heap, 1024 * 1024 * 100);
|
||||
dealloc(heap, large_block);
|
||||
|
||||
// Allocate multiple small blocks
|
||||
void* blocks[100];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
blocks[i] = alloc(128);
|
||||
blocks[i] = alloc(heap, 128);
|
||||
assert(blocks[i] != NULL, "Failed to allocate small block");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
dealloc(blocks[i]);
|
||||
dealloc(heap, blocks[i]);
|
||||
}
|
||||
|
||||
// Stress test with various sizes
|
||||
for (int i = 1; i <= 1000; ++i) {
|
||||
void* p = alloc(i * 64);
|
||||
void* p = alloc(heap, i * 64);
|
||||
assert(p != NULL, "Failed to allocate varying size block");
|
||||
dealloc(p);
|
||||
dealloc(heap, p);
|
||||
}
|
||||
|
||||
// Free in reverse order
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
blocks[i] = alloc(128);
|
||||
blocks[i] = alloc(heap, 128);
|
||||
assert(blocks[i] != NULL, "Failed to allocate small block");
|
||||
}
|
||||
|
||||
for (int i = 99; i >= 0; --i) {
|
||||
dealloc(blocks[i]);
|
||||
dealloc(heap, blocks[i]);
|
||||
}
|
||||
|
||||
// Test memory integrity with various allocation patterns
|
||||
int* nums[10];
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
nums[i] = (int*)alloc(sizeof(int) * 10);
|
||||
nums[i] = (int*)alloc(heap, sizeof(int) * 10);
|
||||
for (int j = 0; j < 10; ++j) {
|
||||
nums[i][j] = i * 10 + j;
|
||||
}
|
||||
|
@ -95,19 +98,17 @@ void test_allocator(bool do_log_heap) {
|
|||
for (int j = 0; j < 10; ++j) {
|
||||
assert(nums[i][j] == i * 10 + j, "Memory corruption detected");
|
||||
}
|
||||
dealloc(nums[i]);
|
||||
dealloc(heap, nums[i]);
|
||||
}
|
||||
|
||||
|
||||
reset_temporary_storage();
|
||||
|
||||
push_allocator(temp);
|
||||
|
||||
int* foo = (int*)alloc(72);
|
||||
int* foo = (int*)alloc(temp, 72);
|
||||
*foo = 1337;
|
||||
void* bar = alloc(69);
|
||||
void* bar = alloc(temp, 69);
|
||||
(void)bar;
|
||||
void* baz = alloc(420);
|
||||
void* baz = alloc(temp, 420);
|
||||
(void)baz;
|
||||
|
||||
assert(*foo == 1337, "Temp memory corruptada");
|
||||
|
@ -116,63 +117,61 @@ void test_allocator(bool do_log_heap) {
|
|||
|
||||
reset_temporary_storage();
|
||||
|
||||
foo = (int*)alloc(72);
|
||||
foo = (int*)alloc(temp, 72);
|
||||
|
||||
assert(old_foo == foo, "Temp allocator goof");
|
||||
|
||||
pop_allocator();
|
||||
|
||||
// Repeated Allocation and Free
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
void* temp = alloc(128);
|
||||
void* temp = alloc(heap, 128);
|
||||
assert(temp != NULL && "Repeated allocation failed");
|
||||
dealloc(temp);
|
||||
dealloc(heap, temp);
|
||||
}
|
||||
|
||||
// Mixed Size Allocations
|
||||
void* mixed_blocks[200];
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
mixed_blocks[i] = alloc(128);
|
||||
mixed_blocks[i] = alloc(heap, 128);
|
||||
} else {
|
||||
mixed_blocks[i] = alloc(1024 * 1024); // 1MB blocks
|
||||
mixed_blocks[i] = alloc(heap, 1024 * 1024); // 1MB blocks
|
||||
}
|
||||
assert(mixed_blocks[i] != NULL && "Mixed size allocation failed");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
dealloc(mixed_blocks[i]);
|
||||
dealloc(heap, mixed_blocks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
if (i % 2 != 0) {
|
||||
dealloc(mixed_blocks[i]);
|
||||
dealloc(heap, mixed_blocks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Fragmentation Stress Test
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
blocks[i] = alloc(256);
|
||||
blocks[i] = alloc(heap, 256);
|
||||
assert(blocks[i] != NULL && "Failed to allocate small block for fragmentation test");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 50; i += 2) {
|
||||
dealloc(blocks[i]);
|
||||
dealloc(heap, blocks[i]);
|
||||
}
|
||||
|
||||
for (int i = 50; i < 100; ++i) {
|
||||
blocks[i] = alloc(128);
|
||||
blocks[i] = alloc(heap, 128);
|
||||
assert(blocks[i] != NULL && "Failed to allocate small block in fragmented heap");
|
||||
}
|
||||
|
||||
for (int i = 50; i < 100; ++i) {
|
||||
dealloc(blocks[i]);
|
||||
dealloc(heap, blocks[i]);
|
||||
}
|
||||
|
||||
for (int i = 1; i < 50; i += 2) {
|
||||
dealloc(blocks[i]);
|
||||
dealloc(heap, blocks[i]);
|
||||
}
|
||||
|
||||
if (do_log_heap) log_heap();
|
||||
|
@ -192,7 +191,8 @@ void test_thread_proc1(Thread* t) {
|
|||
}
|
||||
|
||||
void test_threads() {
|
||||
Thread* t = os_make_thread(test_thread_proc1);
|
||||
|
||||
Thread* t = os_make_thread(test_thread_proc1, get_heap_allocator());
|
||||
os_start_thread(t);
|
||||
os_sleep(20);
|
||||
printf("This should be printed in middle of thread execution\n");
|
||||
|
@ -205,31 +205,34 @@ void test_threads() {
|
|||
}
|
||||
|
||||
void test_allocator_threaded(Thread *t) {
|
||||
|
||||
Allocator heap = get_heap_allocator();
|
||||
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
void* temp = alloc(128);
|
||||
void* temp = alloc(heap, 128);
|
||||
assert(temp != NULL && "Repeated allocation failed");
|
||||
dealloc(temp);
|
||||
dealloc(heap, temp);
|
||||
}
|
||||
|
||||
void* mixed_blocks[40];
|
||||
for (int i = 0; i < 40; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
mixed_blocks[i] = alloc(128);
|
||||
mixed_blocks[i] = alloc(heap, 128);
|
||||
} else {
|
||||
mixed_blocks[i] = alloc(1024 * 1024); // 1MB blocks
|
||||
mixed_blocks[i] = alloc(heap, 1024 * 1024); // 1MB blocks
|
||||
}
|
||||
assert(mixed_blocks[i] != NULL && "Mixed size allocation failed");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 40; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
dealloc(mixed_blocks[i]);
|
||||
dealloc(heap, mixed_blocks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 40; ++i) {
|
||||
if (i % 2 != 0) {
|
||||
dealloc(mixed_blocks[i]);
|
||||
dealloc(heap, mixed_blocks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,43 +242,43 @@ void test_strings() {
|
|||
assert(length_of_null_terminated_string("Test") == 4, "Failed: length_of_null_terminated_string");
|
||||
assert(length_of_null_terminated_string("") == 0, "Failed: length_of_null_terminated_string");
|
||||
|
||||
Allocator heap = get_heap_allocator();
|
||||
|
||||
// Test alloc_string and dealloc_string
|
||||
string alloc_str = alloc_string(10);
|
||||
string alloc_str = alloc_string(heap, 10);
|
||||
assert(alloc_str.data != NULL, "Failed: alloc_string");
|
||||
assert(alloc_str.count == 10, "Failed: alloc_string");
|
||||
dealloc_string(alloc_str);
|
||||
dealloc_string(heap, alloc_str);
|
||||
|
||||
// Test string_concat
|
||||
string str1 = fixed_string("Hello, ");
|
||||
string str2 = fixed_string("World!");
|
||||
string concat_str = string_concat(str1, str2);
|
||||
string concat_str = string_concat(str1, str2, heap);
|
||||
assert(concat_str.count == str1.count + str2.count, "Failed: string_concat");
|
||||
assert(memcmp(concat_str.data, "Hello, World!", concat_str.count) == 0, "Failed: string_concat");
|
||||
dealloc_string(concat_str);
|
||||
dealloc_string(heap, concat_str);
|
||||
|
||||
// Test convert_to_null_terminated_string
|
||||
char* cstr = convert_to_null_terminated_string(str1);
|
||||
char* cstr = convert_to_null_terminated_string(str1, heap);
|
||||
assert(strcmp(cstr, "Hello, ") == 0, "Failed: convert_to_null_terminated_string");
|
||||
dealloc(cstr);
|
||||
dealloc(heap, cstr);
|
||||
|
||||
// Test temp_convert_to_null_terminated_string
|
||||
cstr = temp_convert_to_null_terminated_string(str2);
|
||||
assert(strcmp(cstr, "World!") == 0, "Failed: temp_convert_to_null_terminated_string");
|
||||
// No need to dealloc, it's temporary storage
|
||||
|
||||
// Test sprint
|
||||
string format_str = fixed_string("Number: %d");
|
||||
string formatted_str = sprint(format_str, 42);
|
||||
char* formatted_cstr = convert_to_null_terminated_string(formatted_str);
|
||||
string formatted_str = sprint(heap, format_str, 42);
|
||||
char* formatted_cstr = convert_to_null_terminated_string(formatted_str, heap);
|
||||
assert(strcmp(formatted_cstr, "Number: 42") == 0, "Failed: sprint");
|
||||
dealloc(formatted_str.data);
|
||||
dealloc(formatted_cstr);
|
||||
dealloc(heap, formatted_str.data);
|
||||
dealloc(heap, formatted_cstr);
|
||||
|
||||
// Test tprint
|
||||
string temp_formatted_str = tprint(format_str, 100);
|
||||
formatted_cstr = temp_convert_to_null_terminated_string(temp_formatted_str);
|
||||
assert(strcmp(formatted_cstr, "Number: 100") == 0, "Failed: tprint");
|
||||
// No need to dealloc, it's temporary storage
|
||||
|
||||
// Test print and printf (visual inspection)
|
||||
printf("Expected output: Hello, World!\n");
|
||||
|
@ -308,24 +311,24 @@ void test_strings() {
|
|||
|
||||
// Test handling of empty strings
|
||||
string empty_str = fixed_string("");
|
||||
string concat_empty_str = string_concat(empty_str, empty_str);
|
||||
string concat_empty_str = string_concat(empty_str, empty_str, heap);
|
||||
assert(concat_empty_str.count == 0, "Failed: string_concat with empty strings");
|
||||
dealloc_string(concat_empty_str);
|
||||
dealloc_string(heap, concat_empty_str);
|
||||
|
||||
// Test very large strings (performance test)
|
||||
string large_str1 = alloc_string(1024 * 1024);
|
||||
string large_str2 = alloc_string(1024 * 1024);
|
||||
string large_concat_str = string_concat(large_str1, large_str2);
|
||||
string large_str1 = alloc_string(heap, 1024 * 1024);
|
||||
string large_str2 = alloc_string(heap, 1024 * 1024);
|
||||
string large_concat_str = string_concat(large_str1, large_str2, heap);
|
||||
assert(large_concat_str.count == 2 * 1024 * 1024, "Failed: large string_concat");
|
||||
dealloc_string(large_str1);
|
||||
dealloc_string(large_str2);
|
||||
dealloc_string(large_concat_str);
|
||||
dealloc_string(heap, large_str1);
|
||||
dealloc_string(heap, large_str2);
|
||||
dealloc_string(heap, large_concat_str);
|
||||
|
||||
// Test string with special characters
|
||||
string special_char_str = fixed_string("Special chars: \n\t\r");
|
||||
cstr = convert_to_null_terminated_string(special_char_str);
|
||||
cstr = convert_to_null_terminated_string(special_char_str, heap);
|
||||
assert(strcmp(cstr, "Special chars: \n\t\r") == 0, "Failed: special character string");
|
||||
dealloc(cstr);
|
||||
dealloc(heap, cstr);
|
||||
|
||||
string a = tprintf("Hello, %cs!\n", "balls");
|
||||
string balls1 = string_view(a, 7, 5);
|
||||
|
@ -340,17 +343,15 @@ void test_file_io() {
|
|||
#if TARGET_OS == WINDOWS
|
||||
// Test win32_fixed_utf8_to_null_terminated_wide
|
||||
string utf8_str = fixed_string("Test");
|
||||
u16 *wide_str = win32_fixed_utf8_to_null_terminated_wide(utf8_str);
|
||||
u16 *wide_str = win32_fixed_utf8_to_null_terminated_wide(utf8_str, get_heap_allocator());
|
||||
assert(wide_str != NULL, "Failed: win32_fixed_utf8_to_null_terminated_wide");
|
||||
assert(wide_str[4] == 0, "Failed: win32_fixed_utf8_to_null_terminated_wide");
|
||||
dealloc(wide_str);
|
||||
dealloc(get_heap_allocator(), wide_str);
|
||||
|
||||
// Test temp_win32_fixed_utf8_to_null_terminated_wide
|
||||
push_temp_allocator();
|
||||
wide_str = temp_win32_fixed_utf8_to_null_terminated_wide(utf8_str);
|
||||
assert(wide_str != NULL, "Failed: temp_win32_fixed_utf8_to_null_terminated_wide");
|
||||
assert(wide_str[4] == 0, "Failed: temp_win32_fixed_utf8_to_null_terminated_wide");
|
||||
pop_allocator();
|
||||
#endif
|
||||
|
||||
File file = OS_INVALID_FILE;
|
||||
|
@ -391,12 +392,14 @@ void test_file_io() {
|
|||
bool write_entire_result = os_write_entire_file(fixed_string("entire_test.txt"), write_data);
|
||||
assert(write_entire_result, "Failed: os_write_entire_file");
|
||||
|
||||
Allocator heap = get_heap_allocator();
|
||||
|
||||
string read_data;
|
||||
bool read_entire_result = os_read_entire_file(fixed_string("entire_test.txt"), &read_data);
|
||||
bool read_entire_result = os_read_entire_file(fixed_string("entire_test.txt"), &read_data, heap);
|
||||
assert(read_entire_result, "Failed: os_read_entire_file");
|
||||
assert(strings_match(read_data, write_data), "Failed: os_read_entire_file write/read mismatch");
|
||||
assert(memcmp(read_data.data, write_data.data, write_data.count) == 0, "Failed: os_read_entire_file (content mismatch)");
|
||||
dealloc(read_data.data);
|
||||
dealloc(heap, read_data.data);
|
||||
|
||||
// Test fprint
|
||||
File balls = os_file_open(fixed_string("balls.txt"), O_WRITE | O_CREATE);
|
||||
|
@ -404,7 +407,7 @@ void test_file_io() {
|
|||
fprint(balls, "Hello, %cs!", "Balls");
|
||||
os_file_close(balls);
|
||||
string hello_balls;
|
||||
read_entire_result = os_read_entire_file(fixed_string("balls.txt"), &hello_balls);
|
||||
read_entire_result = os_read_entire_file(fixed_string("balls.txt"), &hello_balls, heap);
|
||||
assert(read_entire_result, "Failed: could not read balls.txt");
|
||||
assert(strings_match(hello_balls, fixed_string("Hello, Balls!")), "Failed: balls read/write mismatch. Expected 'Hello, Balls!', got '%s'", hello_balls);
|
||||
|
||||
|
@ -419,7 +422,7 @@ void test_file_io() {
|
|||
assert(ok, "write integers fail");
|
||||
|
||||
string integers_read;
|
||||
ok = os_read_entire_file(fxstr("integers"), &integers_read);
|
||||
ok = os_read_entire_file(fxstr("integers"), &integers_read, heap);
|
||||
assert(ok, "read integers fail");
|
||||
u64 *new_integers = (u64*)integers_data.data;
|
||||
assert(integers_read.count == integers_data.count, "Failed: big file read/write mismatch. Read was %d and written was %d", integers_read.count, integers_data.count);
|
||||
|
@ -435,6 +438,8 @@ void test_file_io() {
|
|||
assert(delete_ok, "Failed: could not delete entire_test.txt");
|
||||
delete_ok = os_file_delete(fixed_string("balls.txt"));
|
||||
assert(delete_ok, "Failed: could not delete balls.txt");
|
||||
delete_ok = os_file_delete(fixed_string("integers.txt"));
|
||||
assert(delete_ok, "Failed: could not delete integers.txt");
|
||||
}
|
||||
|
||||
void oogabooga_run_tests() {
|
||||
|
@ -453,7 +458,7 @@ void oogabooga_run_tests() {
|
|||
printf("Thread bombing allocator... ");
|
||||
Thread* threads[100];
|
||||
for (int i = 0; i < 100; i++) {
|
||||
threads[i] = os_make_thread(test_allocator_threaded);
|
||||
threads[i] = os_make_thread(test_allocator_threaded, get_heap_allocator());
|
||||
os_start_thread(threads[i]);
|
||||
}
|
||||
for (int i = 0; i < 100; i++) {
|
||||
|
|
Reference in a new issue