Cleanup part 2
This commit is contained in:
parent
5e3ce038b5
commit
d42bf63d41
50
cpp_lib.todo
50
cpp_lib.todo
@ -1,50 +0,0 @@
|
|||||||
[#TODO]
|
|
||||||
[ ] Base layer and OS abstraction for Windows. (Ryan's Win32 platform layer is ~2k lines of code.)
|
|
||||||
• ryan uses os_thread_launch (CreateThread) /join (WaitForSingleObject+CloseHandle)/detach (CloseHandle ?? what type?)
|
|
||||||
See: base_threads
|
|
||||||
just implement the stuff we need for:
|
|
||||||
He launches a bunch of async threads from `main_thread_base_entry_point`
|
|
||||||
• Creating / destroying threads.
|
|
||||||
• rdtsc for timing
|
|
||||||
• Thread primitives (Mutex, Semaphore, etc.)
|
|
||||||
• Thread Creation / Deletion
|
|
||||||
[ ] CreateWindow and other Windows-specific features for handling messaging.
|
|
||||||
[ ] Context should include links to other living thread data (+ save dead threads in debug mode)
|
|
||||||
|
|
||||||
[ ] push_scratch() macro. (basically an auto_release_temp)
|
|
||||||
[ ] Start removing irrelevant header files (for unity build system)
|
|
||||||
|
|
||||||
[ ] ... Mouse / Keyboard inputs
|
|
||||||
[*] This is the order I want to follow, because I need them in thread context.
|
|
||||||
- Entry point(s) `Entry_Point_Main.cpp`
|
|
||||||
-> We can have a lib_init() instead of a clear entry point for now.
|
|
||||||
-> Switch from library to application once I add an entry point
|
|
||||||
-> See how rjf abstracts his entry points for each platform with TCTX.
|
|
||||||
|
|
||||||
[Design Stuff]
|
|
||||||
[ ] "Primary Thread" <- Main entry point thread
|
|
||||||
[ ] "Secondary Thread" <- does all the heavy lifting for the first thread and synchronizes with the first.
|
|
||||||
[ ] Tertiary threads (launched by secondary thread and awaiting work as assigned by Primary and Secondary threads)
|
|
||||||
[ ] Multi-threaded by default with sync points
|
|
||||||
[ ] Need bindings for Semaphore and Mutex
|
|
||||||
[ ] Does calling SetProcessWorkingSetSize(.., -1, -1) cause the program to crash? Why tho.
|
|
||||||
[ ] Maybe we just shouldn't do this?
|
|
||||||
[ ] *our* program memory usage can be calculated by Stack Size + allocations from GPAllocator + allocations from arena.
|
|
||||||
[ ] I want to be able to create new Windows (instances) of the program that can communicate with one another.
|
|
||||||
I want one program to be the "Main" and always in-tray, and the others to be "child instances"
|
|
||||||
[TODO - Low priority]
|
|
||||||
[ ] Fix implementation so all source is just in .cpp files (including templates), and auto-generate forward declares like Vjekoslav does.
|
|
||||||
[ ] Implement Secure Arenas (with VirtualLock, wiping memory with RtlSecureZeroMemory)
|
|
||||||
[ ] Way to serialize and deserialize settings in Text (I think using binary is a mistake here?).
|
|
||||||
[Project Ideas] - order of operations:
|
|
||||||
[ ] Pushbullet replacement should make it easy to understand how data can be securely moved over the internet via a central server.
|
|
||||||
[ ] Signal replacement
|
|
||||||
[ ](Graphics): How do I create a basic overlay that shows the time, date, cpu/gpu temps, frequency, memory usage all the time and responds to global hotkey to show more info
|
|
||||||
|
|
||||||
[Documentation Notes]
|
|
||||||
Main inspirations for this codebase:
|
|
||||||
(1) jonathan blow & jai compiler project
|
|
||||||
(2) casey muratori and "handmade" approach to software
|
|
||||||
(3) ryan fleury and raddebugger codebase
|
|
||||||
|
|
||||||
Always contemplate your impulses
|
|
||||||
@ -1,6 +1,3 @@
|
|||||||
#include "Allocator.h"
|
|
||||||
#include "Base_Thread_Context.h"
|
|
||||||
|
|
||||||
void* internal_alloc (s64 size) {
|
void* internal_alloc (s64 size) {
|
||||||
Allocator allocator = get_context_allocator();
|
Allocator allocator = get_context_allocator();
|
||||||
void* result = allocator.proc(Allocator_Mode::ALLOCATE, size, 0, nullptr, allocator.data);
|
void* result = allocator.proc(Allocator_Mode::ALLOCATE, size, 0, nullptr, allocator.data);
|
||||||
|
|||||||
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
|
|
||||||
#include "error-codes.h"
|
|
||||||
|
|
||||||
enum class Allocator_Mode: s32 {
|
enum class Allocator_Mode: s32 {
|
||||||
ALLOCATE = 0,
|
ALLOCATE = 0,
|
||||||
RESIZE = 1,
|
RESIZE = 1,
|
||||||
@ -103,3 +101,4 @@ template <typename T> T* copy_struct(T* src) {
|
|||||||
T* dst = New<T>(false);
|
T* dst = New<T>(false);
|
||||||
memcpy(dst, src, sizeof(T));
|
memcpy(dst, src, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Arena.h"
|
#include "Arena.h"
|
||||||
#include "Arena_Windows.cpp"
|
#include "Arena_Windows.cpp"
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Allocator.h"
|
|
||||||
#include "Base.h"
|
|
||||||
#include "Base_Thread_Context.h"
|
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
constexpr u32 ARENA_DEFAULT_COMMIT_PAGE_COUNT = 16; // 16 * 4k page = 64kB
|
constexpr u32 ARENA_DEFAULT_COMMIT_PAGE_COUNT = 16; // 16 * 4k page = 64kB
|
||||||
constexpr s64 ARENA_DEFAULT_COMMIT_SIZE_BYTES = 65536;
|
constexpr s64 ARENA_DEFAULT_COMMIT_SIZE_BYTES = 65536;
|
||||||
@ -99,10 +95,6 @@ void extend_committed_pages (Arena* arena, u8* end);
|
|||||||
void free_pages_down_to (Arena* arena, s64 pages_to_keep);
|
void free_pages_down_to (Arena* arena, s64 pages_to_keep);
|
||||||
void arena_delete (Arena* arena);
|
void arena_delete (Arena* arena);
|
||||||
|
|
||||||
// Scoped Macros/Functions for auto_reset and auto_release
|
|
||||||
// usage `Auto_Reset guard(arena);` within a scope.
|
|
||||||
#define auto_reset(x) \
|
|
||||||
Auto_Reset Concat(_auto_reset_guard_, __LINE__)(x)
|
|
||||||
struct Auto_Reset {
|
struct Auto_Reset {
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
u8* starting_point;
|
u8* starting_point;
|
||||||
@ -118,10 +110,6 @@ struct Auto_Reset {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define auto_release_temp() auto_release(get_temp_allocator());
|
|
||||||
|
|
||||||
#define auto_release(x) \
|
|
||||||
Auto_Release Concat(_auto_release_guard_, __LINE__)(x)
|
|
||||||
struct Auto_Release {
|
struct Auto_Release {
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
u8* starting_point;
|
u8* starting_point;
|
||||||
@ -138,8 +126,6 @@ struct Auto_Release {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define push_alignment(x, y) \
|
|
||||||
Push_Alignment Concat(_push_align_guard_, __LINE__)(x, y)
|
|
||||||
struct Push_Alignment { // #rename to Arena_Push_Alignment?
|
struct Push_Alignment { // #rename to Arena_Push_Alignment?
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
u16 original_alignment;
|
u16 original_alignment;
|
||||||
@ -156,24 +142,6 @@ struct Push_Alignment { // #rename to Arena_Push_Alignment?
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define push_arena(x) \
|
|
||||||
Push_Arena Concat(_push_alloc_guard_, __LINE__)(x)
|
|
||||||
struct Push_Arena {
|
|
||||||
Thread_Context* context;
|
|
||||||
Allocator original_allocator;
|
|
||||||
|
|
||||||
Push_Arena(Arena* arena) {
|
|
||||||
Assert(is_valid(arena));
|
|
||||||
context = get_thread_context();
|
|
||||||
Assert(context != nullptr);
|
|
||||||
original_allocator = context->allocator;
|
|
||||||
context->allocator = get_allocator(arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Push_Arena() {
|
|
||||||
context->allocator = original_allocator;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Do this later:
|
// Do this later:
|
||||||
// arena_lock_pages :: (using arena: *Arena, start_address: *u8, byte_count: s64)
|
// arena_lock_pages :: (using arena: *Arena, start_address: *u8, byte_count: s64)
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Allocator.h"
|
|
||||||
#include "Arena.h"
|
|
||||||
|
|
||||||
constexpr s64 ARRAY_ARENA_START_OFFSET = 64;
|
constexpr s64 ARRAY_ARENA_START_OFFSET = 64;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -13,6 +10,8 @@ struct ArenaArray { // downcasts to an ArrayView.
|
|||||||
s64 allocated;
|
s64 allocated;
|
||||||
Arena* arena; // We can probably assume arena is &Array-32
|
Arena* arena; // We can probably assume arena is &Array-32
|
||||||
|
|
||||||
|
ArenaArray() {}
|
||||||
|
|
||||||
T& operator[] (s64 index) {
|
T& operator[] (s64 index) {
|
||||||
#if ARRAY_ENABLE_BOUNDS_CHECKING
|
#if ARRAY_ENABLE_BOUNDS_CHECKING
|
||||||
if (index < 0 || index >= count) { debug_break(); } // index out of bounds
|
if (index < 0 || index >= count) { debug_break(); } // index out of bounds
|
||||||
@ -124,32 +123,32 @@ template <typename T> force_inline void maybe_grow (ArenaArray<T>& array) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> force_inline void array_reserve (ArenaArray<T>& array, s64 desired_item_count) {
|
template <typename T> force_inline void array_reserve (ArenaArray<T>& array, s64 desired_item_count) {
|
||||||
reserve_internal((ArenaArray<void>&)array, desired_item_count, sizeof(T));
|
reserve_internal((ArenaArray<u8>&)array, desired_item_count, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void array_resize (ArenaArray<T>& array, s64 desired_item_count, bool initialize) {
|
template <typename T> void array_resize (ArenaArray<T>& array, s64 desired_item_count, bool initialize) {
|
||||||
s64 old_count = array.count;
|
s64 old_count = array.count;
|
||||||
reserve_internal((ArenaArray<void>&)array, desired_item_count, sizeof(T));
|
reserve_internal((ArenaArray<u8>&)array, desired_item_count, sizeof(T));
|
||||||
array.count = desired_item_count;
|
array.count = desired_item_count;
|
||||||
if (initialize) {
|
if (initialize) {
|
||||||
init_range(array.data, old_count, desired_item_count);
|
init_range(array.data, old_count, desired_item_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 max_array_size (ArenaArray<void>& array) {
|
s64 max_array_size (ArenaArray<u8>& array) {
|
||||||
return reserve_size(array.arena) - sizeof(Arena) - sizeof(ArenaArray<void>);
|
return reserve_size(array.arena) - sizeof(Arena) - sizeof(ArenaArray<u8>);
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_arena_realloc (ArenaArray<void>& array, s64 new_size, s64 old_size) {
|
void array_arena_realloc (ArenaArray<u8>& array, s64 new_size, s64 old_size) {
|
||||||
Assert(new_size <= max_array_size(array));
|
Assert(new_size <= max_array_size(array));
|
||||||
|
|
||||||
void* array_begin = (void*)array.data;
|
u8* array_begin = (u8*)array.data;
|
||||||
void* result_end = array_begin + new_size;
|
void* result_end = (void*)(array_begin + new_size);
|
||||||
|
|
||||||
// Check if we need more pages:
|
// Check if we need more pages:
|
||||||
if (result_end > array.arena.first_uncommitted_page) {
|
if (result_end > array.arena->first_uncommitted_page) {
|
||||||
// Critical error if we run out of address space!
|
// Critical error if we run out of address space!
|
||||||
if (result_end > address_limit(array.arena)) {
|
if (result_end > arena_address_limit(array.arena)) {
|
||||||
// #TODO Log error.
|
// #TODO Log error.
|
||||||
Assert(false); // Failed to allocate because Arena is full and cannot expand
|
Assert(false); // Failed to allocate because Arena is full and cannot expand
|
||||||
return;
|
return;
|
||||||
@ -159,7 +158,7 @@ void array_arena_realloc (ArenaArray<void>& array, s64 new_size, s64 old_size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserve_internal (ArenaArray<void>& array, s64 desired_item_count, s64 element_size) {
|
void reserve_internal (ArenaArray<u8>& array, s64 desired_item_count, s64 element_size) {
|
||||||
if (desired_item_count <= array.allocated) return;
|
if (desired_item_count <= array.allocated) return;
|
||||||
|
|
||||||
array_arena_realloc(array, desired_item_count * element_size, array.allocated * element_size);
|
array_arena_realloc(array, desired_item_count * element_size, array.allocated * element_size);
|
||||||
@ -251,20 +250,3 @@ template <typename T> ArrayView<T> array_copy_as_view (ArenaArray<T>& array) {
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [x] initialize_range
|
|
||||||
// [x] max_array_size
|
|
||||||
// [x] maybe_grow
|
|
||||||
// [x] resize
|
|
||||||
// [x] reserve
|
|
||||||
// [x] reserve_internal
|
|
||||||
// [x] array_arena_realloc
|
|
||||||
// [x] reset_keeping_memory
|
|
||||||
// [x] ordered_remove_by_index
|
|
||||||
// [x] unordered_remove_by_index
|
|
||||||
// [x] insert_at
|
|
||||||
// [x] pop
|
|
||||||
// [x] peek
|
|
||||||
// [x] peek_pointer
|
|
||||||
// [x] delete_range
|
|
||||||
// [x] array_copy
|
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
// API in Arena.h
|
// API in Arena.h
|
||||||
#include "Arena.h"
|
|
||||||
#include "Array.h"
|
|
||||||
#include "General_Purpose_Allocator.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
global std::mutex arena_table_mutex;
|
global std::mutex arena_table_mutex;
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
// Strongly influenced by Array.jai in Basic module.
|
// Strongly influenced by Array.jai in Basic module.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base.h"
|
|
||||||
#include "Allocator.h"
|
|
||||||
|
|
||||||
// #TODO: Array.h
|
// #TODO: Array.h
|
||||||
// [x] Set allocations to use context.allocator interface
|
// [x] Set allocations to use context.allocator interface
|
||||||
// For now, I'm just disabling alignment:
|
// For now, I'm just disabling alignment:
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
#include "Base.h"
|
|
||||||
|
|
||||||
// #TODO Split these up into platform_base (e.g. Windows_Base, Unix_Base...)
|
|
||||||
@ -175,3 +175,16 @@ force_inline s64 Next_Power_Of_Two(s64 v) {
|
|||||||
#define ForArrayStartingAt(_it_, _array_, _start_) for (s64 _it_ = _start_; _it_ < (_array_).count; _it_ += 1)
|
#define ForArrayStartingAt(_it_, _array_, _start_) for (s64 _it_ = _start_; _it_ < (_array_).count; _it_ += 1)
|
||||||
#define ForUpTo(_it_, _end_) for (s64 _it_ = 0; _it_ < _end_; _it_ += 1)
|
#define ForUpTo(_it_, _end_) for (s64 _it_ = 0; _it_ < _end_; _it_ += 1)
|
||||||
|
|
||||||
|
// Scoped Macros/Functions for auto_reset and auto_release
|
||||||
|
// usage `Auto_Reset guard(arena);` within a scope.
|
||||||
|
#define auto_reset(x) \
|
||||||
|
Auto_Reset Concat(_auto_reset_guard_, __LINE__)(x)
|
||||||
|
#define push_allocator(x) Push_Allocator Concat(_push_alloc_guard_, __LINE__)(x)
|
||||||
|
#define push_alignment(x, y) \
|
||||||
|
Push_Alignment Concat(_push_align_guard_, __LINE__)(x, y)
|
||||||
|
#define push_arena(x) \
|
||||||
|
Push_Arena Concat(_push_alloc_guard_, __LINE__)(x)
|
||||||
|
#define auto_release_temp() auto_release(get_temp_allocator());
|
||||||
|
#define auto_release(x) \
|
||||||
|
Auto_Release Concat(_auto_release_guard_, __LINE__)(x)
|
||||||
|
|
||||||
|
|||||||
@ -1,44 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Base.h"
|
|
||||||
|
|
||||||
// Need to sort out how formatted strings and string builders are allocated
|
|
||||||
// Maybe just use context.allocator?
|
|
||||||
// What about temp strings? use context.temp?
|
|
||||||
|
|
||||||
struct string {
|
|
||||||
s64 count;
|
|
||||||
u8* data;
|
|
||||||
// Construct from a string literal or C-string
|
|
||||||
string () { // default constructor
|
|
||||||
count = 0;
|
|
||||||
data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
string (char* cstr) {
|
|
||||||
count = strlen(cstr);
|
|
||||||
data = (u8*)cstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
string (s64 _count, char* str) { count = _count; data = (u8*)str; }
|
|
||||||
string (s64 _count, u8* str) { count = _count; data = str; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// ~ API ~ #TODO
|
|
||||||
string copy_string (string str);
|
|
||||||
bool strings_match(string first_string, string second_string);
|
|
||||||
|
|
||||||
// Unicode stuff
|
|
||||||
string wide_to_utf8 (u16* source, s32 length);
|
|
||||||
|
|
||||||
// string string_view(string n_string, int start_index, int view_count);
|
|
||||||
// string copy_string(char* c_string);
|
|
||||||
// void free(string& n_string);
|
|
||||||
|
|
||||||
bool is_valid(string n_string);
|
|
||||||
bool is_c_string(string n_string);
|
|
||||||
|
|
||||||
char* to_c_string(string n_string);
|
|
||||||
|
|
||||||
string format_string(char* format, ...);
|
|
||||||
string string_from_literal(char* literal);
|
|
||||||
@ -1,4 +1,63 @@
|
|||||||
#include "Base_Thread_Context.h"
|
// See Context_Base in jai, and TCTX in raddebugger:
|
||||||
|
struct Thread_Context {
|
||||||
|
Arena* temp; // Used for temporary allocations, scratch space.
|
||||||
|
Arena* arena; // general purpose local arena
|
||||||
|
|
||||||
|
Allocator allocator;
|
||||||
|
s32 thread_idx;
|
||||||
|
u16 _padding0;
|
||||||
|
u16 GPAllocator_alignment = 16;
|
||||||
|
// Logger logger;
|
||||||
|
// Stack_Trace* stack_trace;
|
||||||
|
// #TODO: other debug information
|
||||||
|
// #TODO:
|
||||||
|
// Array<Thread*> threads_created; // maybe should be linked-list?
|
||||||
|
// Thread* thread_that_created_me = nullptr; // so we can remove from above array
|
||||||
|
// Mutex thread_context_mutex;
|
||||||
|
|
||||||
|
string thread_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
Thread_Context* get_thread_context();
|
||||||
|
|
||||||
|
struct Push_Arena {
|
||||||
|
Thread_Context* context;
|
||||||
|
Allocator original_allocator;
|
||||||
|
|
||||||
|
Push_Arena(Arena* arena) {
|
||||||
|
Assert(is_valid(arena));
|
||||||
|
context = get_thread_context();
|
||||||
|
Assert(context != nullptr);
|
||||||
|
original_allocator = context->allocator;
|
||||||
|
context->allocator = get_allocator(arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Push_Arena() {
|
||||||
|
context->allocator = original_allocator;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Push_Allocator {
|
||||||
|
Thread_Context* context;
|
||||||
|
Allocator old_allocator;
|
||||||
|
|
||||||
|
Push_Allocator (Allocator new_allocator) {
|
||||||
|
context = get_thread_context();
|
||||||
|
old_allocator = context->allocator;
|
||||||
|
context->allocator = new_allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Push_Allocator () {
|
||||||
|
context->allocator = old_allocator;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Thread-local allocators:
|
||||||
|
PROTOTYPING_API Allocator get_temp_allocator();
|
||||||
|
PROTOTYPING_API Allocator get_context_allocator();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// C_LINKAGE thread_static TCTX* tctx_thread_local;
|
// C_LINKAGE thread_static TCTX* tctx_thread_local;
|
||||||
thread_static Thread_Context* thread_local_context;
|
thread_static Thread_Context* thread_local_context;
|
||||||
|
|||||||
@ -1,55 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Allocator.h"
|
|
||||||
#include "Base.h"
|
|
||||||
// #include "Arena.h"
|
|
||||||
|
|
||||||
struct Arena; // #TEMP - Base_Thread_Context and Arena rely on each other, so I have to figure out how to make this less messy (maybe with meta-generated forward declares?)
|
|
||||||
|
|
||||||
// See Context_Base in jai, and TCTX in raddebugger:
|
|
||||||
struct Thread_Context {
|
|
||||||
Arena* temp; // Used for temporary allocations, scratch space.
|
|
||||||
Arena* arena; // general purpose local arena
|
|
||||||
|
|
||||||
Allocator allocator;
|
|
||||||
s32 thread_idx;
|
|
||||||
u16 _padding0;
|
|
||||||
u16 GPAllocator_alignment = 16;
|
|
||||||
// Logger logger;
|
|
||||||
// Stack_Trace* stack_trace;
|
|
||||||
// #TODO: other debug information
|
|
||||||
// #TODO:
|
|
||||||
// Array<Thread*> threads_created; // maybe should be linked-list?
|
|
||||||
// Thread* thread_that_created_me = nullptr; // so we can remove from above array
|
|
||||||
// Mutex thread_context_mutex;
|
|
||||||
|
|
||||||
string thread_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
Thread_Context* get_thread_context();
|
|
||||||
|
|
||||||
// maybe should append line number to guard?
|
|
||||||
// This is stupid, and maybe should be something generated by a metaprogram?
|
|
||||||
#define push_allocator(x) Push_Allocator Concat(_push_alloc_guard_, __LINE__)(x)
|
|
||||||
struct Push_Allocator {
|
|
||||||
Thread_Context* context;
|
|
||||||
Allocator old_allocator;
|
|
||||||
|
|
||||||
Push_Allocator (Allocator new_allocator) {
|
|
||||||
context = get_thread_context();
|
|
||||||
old_allocator = context->allocator;
|
|
||||||
context->allocator = new_allocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Push_Allocator () {
|
|
||||||
context->allocator = old_allocator;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Thread-local allocators:
|
|
||||||
PROTOTYPING_API Allocator get_temp_allocator();
|
|
||||||
PROTOTYPING_API Allocator get_context_allocator();
|
|
||||||
// PROTOTYPING_API void reset_temp_allocator();
|
|
||||||
// PROTOTYPING_API void free_temp_allocator();
|
|
||||||
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
#include "General_Purpose_Allocator.h"
|
|
||||||
#include "Basic.h"
|
#include "Basic.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "error-codes.h"
|
|
||||||
#include "Array.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,4 +1,57 @@
|
|||||||
#include "error-codes.h"
|
enum ErrorSeverity: s32 {
|
||||||
|
SEVERITY_WARNING = 0,
|
||||||
|
SEVERITY_NON_FATAL = 1,
|
||||||
|
SEVERITY_FATAL = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// typedef struct string Native_Error;
|
||||||
|
// Note: Native_Error should down-cast to a string.
|
||||||
|
struct Native_Error {
|
||||||
|
s64 count;
|
||||||
|
u8* data;
|
||||||
|
ErrorSeverity severity = SEVERITY_WARNING;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define Null_Pointer_Check(arg) \
|
||||||
|
if (arg == nullptr) { \
|
||||||
|
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is a null pointer.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Array_Check(arg) \
|
||||||
|
if (!is_valid(arg)) { \
|
||||||
|
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid array.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define String_Check(arg) \
|
||||||
|
if (!Is_Valid(arg)) { return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid string.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); }
|
||||||
|
|
||||||
|
#define Error_Check(error) \
|
||||||
|
if (error != nullptr) { \
|
||||||
|
return error; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// An error from which the program cannot continue (e.g. a segmentation fault)
|
||||||
|
#define New_Fatal_Error(message) \
|
||||||
|
New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||||
|
|
||||||
|
#define New_Error(message) \
|
||||||
|
New_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||||
|
|
||||||
|
#define New_Warning(message) \
|
||||||
|
New_Warning_Internal("%s:%d\n[%s] Warning: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
||||||
|
|
||||||
|
Native_Error* New_Fatal_Error_Internal(char* raw_message, ...);
|
||||||
|
|
||||||
|
Native_Error* New_Error_Internal(char* raw_message, ...);
|
||||||
|
|
||||||
|
Native_Error* New_Warning_Internal(char* raw_message, ...);
|
||||||
|
|
||||||
|
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity);
|
||||||
|
|
||||||
|
PROTOTYPING_API C_API Native_Error* Cleanup_Error(Native_Error* error);
|
||||||
|
|
||||||
|
PROTOTYPING_API C_API Native_Error* Native_Error_Test();
|
||||||
|
|
||||||
|
|
||||||
#include "General_Purpose_Allocator.h"
|
#include "General_Purpose_Allocator.h"
|
||||||
#include <stdio.h> // vsnprintf, printf
|
#include <stdio.h> // vsnprintf, printf
|
||||||
@ -12,7 +65,7 @@
|
|||||||
Native_Error* Create_New_Native_Error_Internal(char* format, va_list args) {
|
Native_Error* Create_New_Native_Error_Internal(char* format, va_list args) {
|
||||||
constexpr s64 ERROR_BUFFER_COUNT = 512;
|
constexpr s64 ERROR_BUFFER_COUNT = 512;
|
||||||
|
|
||||||
push_allocator(GPAllocator());
|
// push_allocator(GPAllocator());
|
||||||
|
|
||||||
auto error = New<Native_Error>(false);
|
auto error = New<Native_Error>(false);
|
||||||
error->data = (u8*)GPAllocator_New(ERROR_BUFFER_COUNT);
|
error->data = (u8*)GPAllocator_New(ERROR_BUFFER_COUNT);
|
||||||
@ -44,7 +97,7 @@ Native_Error* New_Fatal_Error_Internal(char* format, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity) {
|
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity) {
|
||||||
push_allocator(GPAllocator());
|
// push_allocator(GPAllocator());
|
||||||
|
|
||||||
auto error_message = format_string("%s\n > %s", new_error->data, old_error->data).data;
|
auto error_message = format_string("%s\n > %s", new_error->data, old_error->data).data;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
#include "General_Purpose_Allocator.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if GP_ALLOCATOR_TRACK_ALLOCATIONS
|
#if GP_ALLOCATOR_TRACK_ALLOCATIONS
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base.h"
|
|
||||||
#include "Array.h"
|
|
||||||
|
|
||||||
#define GP_ALLOCATOR_TRACK_ALLOCATIONS BUILD_DEBUG
|
#define GP_ALLOCATOR_TRACK_ALLOCATIONS BUILD_DEBUG
|
||||||
#define GP_ALLOCATOR_VERY_DEBUG 0
|
#define GP_ALLOCATOR_VERY_DEBUG 0
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,46 @@
|
|||||||
// #TODO: Integrate Allocator / context.allocator
|
// #TODO: Integrate Allocator / context.allocator
|
||||||
|
|
||||||
#include "Base_String.h"
|
|
||||||
|
// Need to sort out how formatted strings and string builders are allocated
|
||||||
|
// Maybe just use context.allocator?
|
||||||
|
// What about temp strings? use context.temp?
|
||||||
|
|
||||||
|
struct string {
|
||||||
|
s64 count;
|
||||||
|
u8* data;
|
||||||
|
// Construct from a string literal or C-string
|
||||||
|
string () { // default constructor
|
||||||
|
count = 0;
|
||||||
|
data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
string (char* cstr) {
|
||||||
|
count = strlen(cstr);
|
||||||
|
data = (u8*)cstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
string (s64 _count, char* str) { count = _count; data = (u8*)str; }
|
||||||
|
string (s64 _count, u8* str) { count = _count; data = str; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// ~ API ~ #TODO
|
||||||
|
string copy_string (string str);
|
||||||
|
bool strings_match(string first_string, string second_string);
|
||||||
|
|
||||||
|
// Unicode stuff
|
||||||
|
string wide_to_utf8 (u16* source, s32 length);
|
||||||
|
|
||||||
|
// string string_view(string n_string, int start_index, int view_count);
|
||||||
|
// string copy_string(char* c_string);
|
||||||
|
// void free(string& n_string);
|
||||||
|
|
||||||
|
bool is_valid(string n_string);
|
||||||
|
bool is_c_string(string n_string);
|
||||||
|
|
||||||
|
char* to_c_string(string n_string);
|
||||||
|
|
||||||
|
string format_string(char* format, ...);
|
||||||
|
string string_from_literal(char* literal);
|
||||||
|
|
||||||
#include "General_Purpose_Allocator.h"
|
#include "General_Purpose_Allocator.h"
|
||||||
#include <stdio.h> // vsnprintf
|
#include <stdio.h> // vsnprintf
|
||||||
@ -108,3 +148,4 @@ string wide_to_utf8 (u16* source, s32 length) {
|
|||||||
|
|
||||||
return utf8_string;
|
return utf8_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,58 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Base.h"
|
|
||||||
|
|
||||||
enum ErrorSeverity: s32 {
|
|
||||||
SEVERITY_WARNING = 0,
|
|
||||||
SEVERITY_NON_FATAL = 1,
|
|
||||||
SEVERITY_FATAL = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "Base_String.h"
|
|
||||||
// typedef struct string Native_Error;
|
|
||||||
// Note: Native_Error should down-cast to a string.
|
|
||||||
struct Native_Error {
|
|
||||||
s64 count;
|
|
||||||
u8* data;
|
|
||||||
ErrorSeverity severity = SEVERITY_WARNING;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define Null_Pointer_Check(arg) \
|
|
||||||
if (arg == nullptr) { \
|
|
||||||
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is a null pointer.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Array_Check(arg) \
|
|
||||||
if (!is_valid(arg)) { \
|
|
||||||
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid array.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define String_Check(arg) \
|
|
||||||
if (!Is_Valid(arg)) { return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid string.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); }
|
|
||||||
|
|
||||||
#define Error_Check(error) \
|
|
||||||
if (error != nullptr) { \
|
|
||||||
return error; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// An error from which the program cannot continue (e.g. a segmentation fault)
|
|
||||||
#define New_Fatal_Error(message) \
|
|
||||||
New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
|
||||||
|
|
||||||
#define New_Error(message) \
|
|
||||||
New_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
|
||||||
|
|
||||||
#define New_Warning(message) \
|
|
||||||
New_Warning_Internal("%s:%d\n[%s] Warning: %s.", __FILE__, __LINE__, __FUNCTION__, message)
|
|
||||||
|
|
||||||
Native_Error* New_Fatal_Error_Internal(char* raw_message, ...);
|
|
||||||
|
|
||||||
Native_Error* New_Error_Internal(char* raw_message, ...);
|
|
||||||
|
|
||||||
Native_Error* New_Warning_Internal(char* raw_message, ...);
|
|
||||||
|
|
||||||
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity);
|
|
||||||
|
|
||||||
PROTOTYPING_API C_API Native_Error* Cleanup_Error(Native_Error* error);
|
|
||||||
|
|
||||||
PROTOTYPING_API C_API Native_Error* Native_Error_Test();
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Base.h"
|
|
||||||
#include "error-codes.h"
|
|
||||||
|
|
||||||
#include "General_Purpose_Allocator.h"
|
|
||||||
#include "Array.h"
|
|
||||||
#include "Basic.h"
|
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_break();
|
// debug_break();
|
||||||
|
|
||||||
{ OS_Process_Info* info = &os_state_w32.process_info;
|
{ OS_Process_Info* info = &os_state_w32.process_info;
|
||||||
DWORD length = GetCurrentDirectoryW(0, 0);
|
DWORD length = GetCurrentDirectoryW(0, 0);
|
||||||
|
|||||||
@ -1,10 +1,20 @@
|
|||||||
#include "lib/Base/Base.cpp"
|
// This is quite disorganized. There must be a better way to do this by moving the stuff that requires forward declaration to the top
|
||||||
|
// with a metaprogram.
|
||||||
|
|
||||||
|
#include "lib/Base/Base.h"
|
||||||
|
#include "lib/Base/Allocator.h"
|
||||||
|
#include "lib/Base/Array.h"
|
||||||
|
#include "lib/Base/General_Purpose_Allocator.h"
|
||||||
|
#include "lib/Base/Arena.h"
|
||||||
|
#include "lib/Base/Arena_Array.h"
|
||||||
|
|
||||||
|
#include "lib/Base/String.cpp"
|
||||||
|
#include "lib/Base/ErrorCodes.cpp"
|
||||||
#include "lib/Base/Arena.cpp"
|
#include "lib/Base/Arena.cpp"
|
||||||
|
|
||||||
#include "lib/Base/Arena_Table.cpp"
|
#include "lib/Base/Arena_Table.cpp"
|
||||||
#include "lib/Base/Base_Thread_Context.cpp"
|
#include "lib/Base/Base_Thread_Context.cpp"
|
||||||
#include "lib/Base/General_Purpose_Allocator.cpp"
|
|
||||||
#include "lib/Base/Allocator.cpp"
|
#include "lib/Base/Allocator.cpp"
|
||||||
|
#include "lib/Base/General_Purpose_Allocator.cpp"
|
||||||
#include "lib/Base/Basic.cpp"
|
#include "lib/Base/Basic.cpp"
|
||||||
#include "lib/Base/ErrorCodes.cpp"
|
|
||||||
#include "lib/Base/String.cpp"
|
|
||||||
#include "lib/Base/Timing.cpp"
|
#include "lib/Base/Timing.cpp"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user