diff --git a/.gitignore b/.gitignore index 199a813..287ebec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/** *.exe thirdparty/** -~thirdparty/odin/core/** \ No newline at end of file +~thirdparty/odin/core/** +logs diff --git a/code/api.odin b/code/api.odin index b1e5b4c..4e0f85f 100644 --- a/code/api.odin +++ b/code/api.odin @@ -27,8 +27,11 @@ ModuleAPI :: struct { } @export -startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8 ) +startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ Logger ) { + init( & memory.logger, "Sectr", host_logger.file_path, host_logger.file ) + context.logger = to_odin_logger( & memory.logger ) + // Setup memory for the first time { arena_size :: size_of( mem.Arena) @@ -53,6 +56,7 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8 ) context.allocator = tracked_allocator( transient ) context.temp_allocator = tracked_allocator( temp ) } + state := new( State, tracked_allocator( memory.persistent ) ) using state @@ -64,12 +68,13 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8 ) screen_height = 1000 win_title : cstring = "Sectr Prototype" rl.InitWindow( screen_width, screen_height, win_title ) + log( "Raylib initialized and window opened" ) // Determining current monitor and setting the target frametime based on it.. monitor_id = rl.GetCurrentMonitor () monitor_refresh_hz = rl.GetMonitorRefreshRate( monitor_id ) rl.SetTargetFPS( monitor_refresh_hz ) - fmt.println( "Set target FPS to: %v", monitor_refresh_hz ) + log( fmt.tprintf( "Set target FPS to: %v", monitor_refresh_hz ) ) // Basic Font Setup { @@ -80,6 +85,7 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8 ) rl.GuiSetFont( font_rec_mono_semicasual_reg ) // TODO(Ed) : Does this do anything? default_font = font_rec_mono_semicasual_reg + log( "Default font loaded" ) } } @@ -102,10 +108,11 @@ sectr_shutdown :: proc() rl.UnloadFont ( state.font_rec_mono_semicasual_reg ) rl.CloseWindow() } + log("Module shutdown complete") } @export -reload :: proc( live_mem : virtual.Arena, snapshot_mem : []u8 ) +reload :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ Logger ) { using memory; block := live_mem.curr_block @@ -120,6 +127,8 @@ reload :: proc( live_mem : virtual.Arena, snapshot_mem : []u8 ) persistent = cast( ^TrackedAllocator ) & persistent_slice[0] transient = cast( ^TrackedAllocator ) & transient_slice[0] temp = cast( ^TrackedAllocator ) & temp_slice[0] + + log("Module reloaded") } // TODO(Ed) : This lang really not have a fucking swap? @@ -152,32 +161,26 @@ update :: proc() -> b32 } }} - DO_NOT_CONTINUE : b32 = false - if debug_actions.play_replay { switch replay.mode { case ReplayMode.Off : { if ! file_exists( Path_Input_Replay ) { save_snapshot( & memory.snapshot[0] ) replay_recording_begin( Path_Input_Replay ) - break } else { load_snapshot( & memory.snapshot[0] ) replay_playback_begin( Path_Input_Replay ) - break } } case ReplayMode.Playback : { replay_playback_end() load_snapshot( & memory.snapshot[0] ) - break } case ReplayMode.Record : { replay_recording_end() load_snapshot( & memory.snapshot[0] ) replay_playback_begin( Path_Input_Replay ) - break } }} diff --git a/code/assert.odin b/code/assert.odin new file mode 100644 index 0000000..9f0d41a --- /dev/null +++ b/code/assert.odin @@ -0,0 +1,31 @@ +package sectr + +import "base:runtime" +import "core:os" + +ensure :: proc( condition : b32, msg : string, location := #caller_location ) +{ + if ! condition { + return + } + log( msg, LogLevel.Warning, location ) + runtime.debug_trap() +} + +// TODO(Ed) : Setup exit codes! +fatal :: proc ( msg : string, exit_code : int = -1, location := #caller_location ) +{ + log( msg, LogLevel.Fatal, location ) + runtime.debug_trap() + os.exit( exit_code ) +} + +verify :: proc ( condition : b32, msg : string, exit_code : int = -1, location := #caller_location ) +{ + if ! condition { + return + } + log( msg, LogLevel.Fatal, location ) + runtime.debug_trap() + os.exit( exit_code ) +} diff --git a/code/env.odin b/code/env.odin index d974de8..d7c200b 100644 --- a/code/env.odin +++ b/code/env.odin @@ -21,7 +21,8 @@ Memory :: struct { transient : ^ TrackedAllocator, temp : ^ TrackedAllocator, - replay : ReplayState + replay : ReplayState, + logger : Logger, } State :: struct { @@ -93,6 +94,11 @@ poll_debug_actions :: proc( actions : ^ DebugActions, input : ^ InputState ) } save_snapshot :: proc( snapshot : [^]u8 ) { + state := get_state() + + // state.font_rec_mono_semicasual_reg + // state.default_font + live_ptr := cast( ^ rawptr ) memory.live.curr_block.base mem.copy_non_overlapping( & snapshot[0], live_ptr, memory_chunk_size ) } @@ -118,25 +124,12 @@ replay_recording_begin :: proc( path : string ) { if file_exists( path ) { result := os.remove( path ) - if ( result != os.ERROR_NONE ) - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Failed to delete replay file before beginning a new one" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } + verify( result != os.ERROR_NONE, "Failed to delete replay file before beginning a new one" ) } replay_file, open_error := os.open( path, os.O_RDWR | os.O_CREATE ) - if ( open_error != os.ERROR_NONE ) - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Failed to create or open the replay file" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } + verify( open_error != os.ERROR_NONE, "Failed to create or open the replay file" ) + os.seek( replay_file, 0, 0 ) replay := & memory.replay @@ -154,34 +147,20 @@ replay_recording_end :: proc() { replay_playback_begin :: proc( path : string ) { - if ! file_exists( path ) - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Failed to create or open the replay file" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } + verify( ! file_exists( path ), "Failed to find replay file" ) replay_file, open_error := os.open( path, os.O_RDWR | os.O_CREATE ) - if ( open_error != os.ERROR_NONE ) - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Failed to create or open the replay file" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } - // TODO(Ed): WE need to wrap any actions that can throw a fatal like this. Files need a grime wrap. + verify( open_error != os.ERROR_NONE, "Failed to create or open the replay file" ) + os.seek( replay_file, 0, 0 ) replay := & memory.replay replay.active_file = replay_file - replay.mode = ReplayMode.Playback + replay.mode = ReplayMode.Playback } replay_playback_end :: proc() { - input := get_state().input + input := get_state().input replay := & memory.replay replay.mode = ReplayMode.Off os.seek( replay.active_file, 0, 0 ) diff --git a/code/filesystem.odin b/code/filesystem.odin index 2517622..6831885 100644 --- a/code/filesystem.odin +++ b/code/filesystem.odin @@ -11,7 +11,7 @@ copy_file_sync :: proc( path_src, path_dst: string ) -> b32 { path_info, result := os.stat( path_src, context.temp_allocator ) if result != os.ERROR_NONE { - fmt.println("Error getting file info: ", result ) + logf("Could not get file info: %v", result, LogLevel.Error ) return false } file_size = path_info.size @@ -19,14 +19,14 @@ copy_file_sync :: proc( path_src, path_dst: string ) -> b32 src_content, result := os.read_entire_file( path_src, context.temp_allocator ) if ! result { - fmt.println( "Failed to read file to copy" ) + logf( "Failed to read file to copy: %v", path_src, LogLevel.Error ) runtime.debug_trap() return false } result = os.write_entire_file( path_dst, src_content, false ) if ! result { - fmt.println( "Failed to copy file") + logf( "Failed to copy file: %v", path_dst, LogLevel.Error ) runtime.debug_trap() return false } diff --git a/code/host/host.odin b/code/host/host.odin index 751e006..2793b36 100644 --- a/code/host/host.odin +++ b/code/host/host.odin @@ -15,6 +15,7 @@ import "core:mem/virtual" Petabyte :: 1024 * Terabyte Exabyte :: 1024 * Petabyte import "core:os" + file_resize :: os.ftruncate import "core:strings" import "core:time" import rl "vendor:raylib" @@ -24,9 +25,15 @@ TrackedAllocator :: sectr.TrackedAllocator tracked_allocator :: sectr.tracked_allocator tracked_allocator_init :: sectr.tracked_allocator_init +LogLevel :: sectr.LogLevel +log :: sectr.log +fatal :: sectr.fatal +verify :: sectr.verify + path_snapshot :: "VMemChunk_1.snapshot" when ODIN_OS == runtime.Odin_OS_Type.Windows { + path_logs :: "../logs" path_sectr_module :: "sectr.dll" path_sectr_live_module :: "sectr_live.dll" path_sectr_debug_symbols :: "sectr.pdb" @@ -65,29 +72,14 @@ setup_memory :: proc () -> VMemChunk base_address : rawptr = transmute( rawptr) u64(Terabyte * 1) result := arena_init_static( & sectr_live, base_address, sectr.memory_chunk_size, sectr.memory_chunk_size ) - if result != runtime.Allocator_Error.None - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Failed to allocate live memory for the sectr module" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } + verify( result != runtime.Allocator_Error.None, "Failed to allocate live memory for the sectr module" ) } // Setup memory mapped io for snapshots { - file_resize :: os.ftruncate - snapshot_file, open_error := os.open( path_snapshot, os.O_RDWR | os.O_CREATE ) - if ( open_error != os.ERROR_NONE ) - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Failed to open snapshot file for the sectr module" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } + verify( open_error != os.ERROR_NONE, "Failed to open snapshot file for the sectr module" ) + file_info, stat_code := os.stat( path_snapshot ) { if file_info.size != sectr.memory_chunk_size { @@ -95,16 +87,10 @@ setup_memory :: proc () -> VMemChunk } } - map_error : virtual.Map_File_Error - sectr_snapshot, map_error = virtual.map_file_from_file_descriptor( uintptr(snapshot_file), { virtual.Map_File_Flag.Read, virtual.Map_File_Flag.Write } ) - if map_error != virtual.Map_File_Error.None - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Failed to allocate snapshot memory for the sectr module" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } + map_error : virtual.Map_File_Error + map_flags : virtual.Map_File_Flags = { virtual.Map_File_Flag.Read, virtual.Map_File_Flag.Write } + sectr_snapshot, map_error = virtual.map_file_from_file_descriptor( uintptr(snapshot_file), map_flags ) + verify( map_error != virtual.Map_File_Error.None, "Failed to allocate snapshot memory for the sectr module" ) os.close(snapshot_file) } @@ -112,8 +98,7 @@ setup_memory :: proc () -> VMemChunk // Reassign default allocators for host memory.og_allocator = context.allocator memory.og_temp_allocator = context.temp_allocator - context.allocator = tracked_allocator( & memory.host_persistent ) - context.temp_allocator = tracked_allocator( & memory.host_transient ) + log("Memory setup") return memory; } @@ -121,10 +106,9 @@ load_sectr_api :: proc ( version_id : i32 ) -> sectr.ModuleAPI { loaded_module : sectr.ModuleAPI - write_time, - result := os.last_write_time_by_name("sectr.dll") + write_time, result := os.last_write_time_by_name("sectr.dll") if result != os.ERROR_NONE { - fmt. println("Could not resolve the last write time for sectr.dll") + log( "Could not resolve the last write time for sectr.dll", LogLevel.Warning ) runtime.debug_trap() return {} } @@ -134,8 +118,7 @@ load_sectr_api :: proc ( version_id : i32 ) -> sectr.ModuleAPI lib, load_result := dynlib.load_library( live_file ) if ! load_result { - // TODO(Ed) : Setup a proper logging interface - fmt. println( "Failed to load the sectr module." ) + log( "Failed to load the sectr module.", LogLevel.Warning ) runtime.debug_trap() return {} } @@ -159,6 +142,7 @@ load_sectr_api :: proc ( version_id : i32 ) -> sectr.ModuleAPI return {} } + log("Loaded sectr API") loaded_module = { lib = lib, write_time = write_time, @@ -179,9 +163,10 @@ unload_sectr_api :: proc ( module : ^ sectr.ModuleAPI ) dynlib.unload_library( module.lib ) os.remove( path_sectr_live_module ) module^ = {} + log("Unloaded sectr API") } -sync_sectr_api :: proc ( sectr_api : ^ sectr.ModuleAPI, memory : ^ VMemChunk ) +sync_sectr_api :: proc ( sectr_api : ^ sectr.ModuleAPI, memory : ^ VMemChunk, logger : ^ sectr.Logger ) { if write_time, result := os.last_write_time_by_name( path_sectr_module ); result == os.ERROR_NONE && sectr_api.write_time != write_time @@ -194,13 +179,9 @@ sync_sectr_api :: proc ( sectr_api : ^ sectr.ModuleAPI, memory : ^ VMemChunk ) time.sleep( time.Millisecond ) sectr_api ^ = load_sectr_api( version_id ) - if sectr_api.lib_version == 0 { - fmt.println("Failed to hot-reload the sectr module") - runtime.debug_trap() - os.exit(-1) - // TODO(Ed) : Figure out the error code enums.. - } - sectr_api.reload( memory.sectr_live, memory.sectr_snapshot ) + verify( sectr_api.lib_version == 0, "Failed to hot-reload the sectr module" ) + + sectr_api.reload( memory.sectr_live, memory.sectr_snapshot, logger ) } } @@ -209,6 +190,32 @@ main :: proc() state : RuntimeState using state + path_logger_finalized : string + { + startup_time := time.now() + year, month, day := time.date( startup_time) + hour, min, sec := time.clock_from_time( startup_time) + + if ! os.is_dir( path_logs ) { + os.make_directory( path_logs ) + } + + timestamp := fmt.tprintf("%04d-%02d-%02d_%02d-%02d-%02d", year, month, day, hour, min, sec) + path_logger_finalized = strings.clone( fmt.tprintf( "%s/sectr_%v.log", path_logs, timestamp) ) + } + logger : sectr.Logger + sectr.init( & logger, "Sectr Host", fmt.tprintf( "%s/sectr.log", path_logs ) ) + context.logger = sectr.to_odin_logger( & logger ) + { + // Log System Context + backing_builder : [16 * Kilobyte] u8 + builder := strings.builder_from_bytes( backing_builder[:] ) + fmt.sbprintf( & builder, "Core Count: %v, ", os.processor_core_count() ) + fmt.sbprintf( & builder, "Page Size: %v", os.get_page_size() ) + + sectr.log( strings.to_string(builder) ) + } + // Basic Giant VMem Block { // By default odin uses a growing arena for the runtime context @@ -218,28 +225,26 @@ main :: proc() memory = setup_memory() } + // TODO(Ed): Cannot use the manually created allocators for the host. Not sure why + // context.allocator = tracked_allocator( & memory.host_persistent ) + // context.temp_allocator = tracked_allocator( & memory.host_transient ) + // Load the Enviornment API for the first-time { - sectr_api = load_sectr_api( 1 ) - if sectr_api.lib_version == 0 { - // TODO(Ed) : Setup a proper logging interface - fmt. println( "Failed to initially load the sectr module" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } + sectr_api = load_sectr_api( 1 ) + verify( sectr_api.lib_version == 0, "Failed to initially load the sectr module" ) } running = true; memory = memory sectr_api = sectr_api - sectr_api.startup( memory.sectr_live, memory.sectr_snapshot ) + sectr_api.startup( memory.sectr_live, memory.sectr_snapshot, & logger ) // TODO(Ed) : This should have an end status so that we know the reason the engine stopped. for ; running ; { // Hot-Reload - sync_sectr_api( & sectr_api, & memory ) + sync_sectr_api( & sectr_api, & memory, & logger ) running = sectr_api.update() sectr_api.render() @@ -254,4 +259,8 @@ main :: proc() sectr_api.shutdown() unload_sectr_api( & sectr_api ) + + log("Succesfuly closed") + os.close( logger.file ) + os.rename( logger.file_path, path_logger_finalized ) } diff --git a/code/host/memory_windows.odin b/code/host/memory_windows.odin index 30ef446..4ba848d 100644 --- a/code/host/memory_windows.odin +++ b/code/host/memory_windows.odin @@ -2,11 +2,13 @@ // This was made becaause odin didn't expose the base_address param that virtual alloc allows. package host +import "base:runtime" import "core:mem" import "core:mem/virtual" import win32 "core:sys/windows" +when ODIN_OS == runtime.Odin_OS_Type.Windows { @(private="file") virtual_Platform_Memory_Block :: struct { block: virtual.Memory_Block, @@ -124,3 +126,6 @@ arena_init_static :: proc(arena: ^virtual.Arena, base_address : rawptr, arena.total_reserved = arena.curr_block.reserved return } + +// END WINDOWS CHECK WRAP +} diff --git a/code/input.odin b/code/input.odin index 6230177..bb25206 100644 --- a/code/input.odin +++ b/code/input.odin @@ -16,7 +16,7 @@ btn_pressed :: proc( btn : DigitalBtn ) -> b32 { } pressed :: proc { - btn_pressed + btn_pressed, } MaxKeyboardKeys :: 256 @@ -286,7 +286,7 @@ poll_input :: proc( old, new : ^ InputState ) input_process_digital_btn :: proc ( old_state, new_state : ^ DigitalBtn, is_down : b32 ) { new_state.ended_down = is_down - had_transition := old_state.ended_down != new_state.ended_down + had_transition := old_state.ended_down != new_state.ended_down if had_transition { new_state.half_transitions += 1 } @@ -477,7 +477,7 @@ to_raylib_key :: proc ( key : i32 ) -> rl.KeyboardKey { rl.KeyboardKey.KP_SUBTRACT, rl.KeyboardKey.KP_MULTIPLY, rl.KeyboardKey.KP_DIVIDE, - rl.KeyboardKey.KP_ENTER + rl.KeyboardKey.KP_ENTER } return raylib_key_lookup_table[ key ] } diff --git a/code/logger.odin b/code/logger.odin new file mode 100644 index 0000000..d4c77ce --- /dev/null +++ b/code/logger.odin @@ -0,0 +1,125 @@ +package sectr + +import "base:runtime" +import "core:fmt" +import "core:mem" +import "core:os" +import "core:strings" +import "core:time" +import core_log "core:log" + +Max_Logger_Message_Width :: 80 + +LogLevel :: core_log.Level + +Logger :: struct { + file_path : string, + file : os.Handle, + id : string, +} + +to_odin_logger :: proc ( logger : ^ Logger ) -> core_log.Logger { + return { logger_interface, logger, core_log.Level.Debug, core_log.Default_File_Logger_Opts } +} + +init :: proc ( logger : ^ Logger, id : string, file_path : string, file := os.INVALID_HANDLE ) +{ + if file == os.INVALID_HANDLE + { + logger_file, result_code := os.open( file_path, os.O_RDWR | os.O_CREATE ) + if result_code != os.ERROR_NONE { + // Log failures are fatal and must never occur at runtime (there is no logging) + runtime.debug_trap() + os. exit( -1 ) + // TODO(Ed) : Figure out the error code enums.. + } + logger.file = logger_file + } + else { + logger.file = file + } + logger.file_path = file_path + logger.id = id + + context.logger = { logger_interface, logger, core_log.Level.Debug, core_log.Default_File_Logger_Opts } + log("Initialized Logger") + when false { + log("This sentence is over 80 characters long on purpose to test the ability of this fucking logger to properfly fucking wrap long as fuck logs with a new line and then at the end of that pad it with the appropraite signature.") + } +} + +logger_interface :: proc ( + logger_data : rawptr, + level : core_log.Level, + text : string, + options : core_log.Options, + location := #caller_location ) +{ + logger := cast(^ Logger) logger_data + + @static builder_backing : [16 * Kilobyte] byte; { + mem.set( raw_data( builder_backing[:] ), 0, len(builder_backing) ) + } + builder := strings.builder_from_bytes( builder_backing[:] ) + + first_line_length := len(text) > Max_Logger_Message_Width ? Max_Logger_Message_Width : len(text) + first_line := transmute(string) text[ 0 : first_line_length ] + fmt.sbprintf( & builder, "%-*s ", Max_Logger_Message_Width, first_line ) + + // Signature + { + when time.IS_SUPPORTED + { + if core_log.Full_Timestamp_Opts & options != nil { + fmt.sbprint( & builder, "[") + + t := time.now() + y, m, d := time.date(t) + h, min, s := time.clock(t) + + if .Date in options { + fmt.sbprintf( & builder, "%d-%02d-%02d ", y, m, d ) + } + if .Time in options { + fmt.sbprintf( & builder, "%02d:%02d:%02d", h, min, s) + } + + fmt.sbprint( & builder, "] ") + } + } + core_log.do_level_header( options, level, & builder ) + + if logger.id != "" { + fmt.sbprintf( & builder, "[%s] ", logger.id ) + } + core_log.do_location_header( options, & builder, location ) + } + + // Oversized message handling + if len(text) > Max_Logger_Message_Width + { + offset := Max_Logger_Message_Width + bytes := transmute([]u8) text + for left := len(bytes) - Max_Logger_Message_Width; left > 0; left -= Max_Logger_Message_Width + { + fmt.sbprintf( & builder, "\n" ) + subset_length := len(text) - offset + if subset_length > Max_Logger_Message_Width { + subset_length = Max_Logger_Message_Width + } + subset := slice_ptr( ptr_offset( raw_data(bytes), offset), subset_length ) + fmt.sbprintf( & builder, "%s", transmute(string)subset ) + offset += Max_Logger_Message_Width + } + } + + fmt.fprintln( logger.file, strings.to_string(builder) ) +} + +log :: proc ( msg : string, level := LogLevel.Info, loc := #caller_location ) { + core_log.log( level, msg, location = loc ) +} + +logf :: proc ( fmt : string, args : ..any, level := LogLevel.Info, loc := #caller_location ) { + core_log.logf( level, fmt, args, location = loc ) +} diff --git a/code/memory.odin b/code/memory.odin index 0b335d8..a5a0f31 100644 --- a/code/memory.odin +++ b/code/memory.odin @@ -34,6 +34,7 @@ tracked_allocator :: proc ( self : ^ TrackedAllocator ) -> Allocator { return tracking_allocator( & self.tracker ) } +// TODO(Ed): These allocators are bad... not sure why. tracked_allocator_init :: proc( size, internals_size : int, allocator := context.allocator ) -> TrackedAllocator { result : TrackedAllocator @@ -44,20 +45,22 @@ tracked_allocator_init :: proc( size, internals_size : int, allocator := context raw_size := backing_size + internals_size raw_mem, raw_mem_code := alloc( raw_size, mem.DEFAULT_ALIGNMENT, allocator ) - if ( raw_mem_code != mem.Allocator_Error.None ) - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Failed to allocate memory for the TrackingAllocator" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } - arena_init( & result.backing, slice_ptr( cast( ^ byte) raw_mem, backing_size ) ) - arena_init( & result.internals, slice_ptr( memory_after( result.backing.data), internals_size ) ) + verify( raw_mem_code != mem.Allocator_Error.None, "Failed to allocate memory for the TrackingAllocator" ) + + backing_slice := slice_ptr( cast( ^ byte) raw_mem, backing_size ) + internals_slice := slice_ptr( memory_after( backing_slice), internals_size ) + + arena_init( & result.backing, backing_slice ) + arena_init( & result.internals, internals_slice ) backing_allocator := arena_allocator( & result.backing ) internals_allocator := arena_allocator( & result.internals ) tracking_allocator_init( & result.tracker, backing_allocator, internals_allocator ) + { + tracker_arena := cast(^Arena) result.tracker.backing.data + arena_len := len( tracker_arena.data ) + verify( arena_len != len(result.backing.data), "BAD SIZE ON TRACKER'S ARENA" ) + } return result } @@ -68,14 +71,7 @@ tracked_allocator_init_vmem :: proc( vmem : [] byte, internals_size : int ) -> ^ backing_size := len(vmem) - internals_size raw_size := backing_size + internals_size - if backing_size < 0 || len(vmem) < raw_size - { - // TODO(Ed) : Setup a proper logging interface - fmt. printf( "Provided virtual memory slice is not large enough to hold the TrackedAllocator" ) - runtime.debug_trap() - os. exit( -1 ) - // TODO(Ed) : Figure out the error code enums.. - } + verify( backing_size < 0 || len(vmem) < raw_size, "Provided virtual memory slice is not large enough to hold the TrackedAllocator" ) result := cast( ^ TrackedAllocator) & vmem[0] result_slice := slice_ptr( & vmem[0], tracking_allocator_size )