From 4d00c2b800266346bda25e32797f6a4319c2ef51 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 8 Aug 2021 14:29:45 +0100 Subject: [PATCH] `Allocator_Error.Mode_Not_Implemented`; Minor improvement to `map` runtime procedures --- core/mem/alloc.odin | 30 +++++-- core/mem/allocators.odin | 114 ++----------------------- core/os/os.odin | 4 +- core/os/os2/heap_windows.odin | 2 +- core/runtime/core.odin | 9 +- core/runtime/dynamic_map_internal.odin | 2 +- 6 files changed, 41 insertions(+), 120 deletions(-) diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index 0da7a9708..f886f4bb9 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -31,10 +31,11 @@ Allocator_Query_Info :: struct { Allocator_Error :: runtime.Allocator_Error; /* Allocator_Error :: enum byte { - None = 0, - Out_Of_Memory = 1, - Invalid_Pointer = 2, - Invalid_Argument = 3, + None = 0, + Out_Of_Memory = 1, + Invalid_Pointer = 2, + Invalid_Argument = 3, + Mode_Not_Implemented = 4, } */ Allocator_Proc :: runtime.Allocator_Proc; @@ -121,7 +122,15 @@ resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_AL return nil; } data, err := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc); - _ = err; + if err == .Mode_Not_Implemented { + data, err = allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc); + if err != nil { + return nil; + } + runtime.copy(data, byte_slice(ptr, old_size)); + _, err = allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc); + return raw_data(data); + } return raw_data(data); } @@ -140,7 +149,16 @@ resize_bytes :: proc(old_data: []byte, new_size: int, alignment: int = DEFAULT_A } else if ptr == nil { return allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc); } - return allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc); + data, err := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, loc); + if err == .Mode_Not_Implemented { + data, err = allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, loc); + if err != nil { + return data, err; + } + runtime.copy(data, old_data); + _, err = allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, old_size, loc); + } + return data, err; } query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: Allocator_Mode_Set) { diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index 258aea3a5..2aea430cb 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -67,8 +67,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return byte_slice(ptr, size), nil; case .Free: - // NOTE(bill): Free all at once - // Use Arena_Temp_Memory if you want to free a block + return nil, .Mode_Not_Implemented; case .Free_All: arena.offset = 0; @@ -84,7 +83,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, nil; case .Query_Info: - return nil, nil; + return nil, .Mode_Not_Implemented; } return nil, nil; @@ -262,7 +261,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, nil; case .Query_Info: - return nil, nil; + return nil, .Mode_Not_Implemented; } return nil, nil; @@ -426,7 +425,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, } return nil, nil; case .Query_Info: - return nil, nil; + return nil, .Mode_Not_Implemented; } return nil, nil; @@ -561,7 +560,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, nil; case .Query_Info: - return nil, nil; + return nil, .Mode_Not_Implemented; } return nil, nil; @@ -602,7 +601,7 @@ dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode case .Alloc: return dynamic_pool_alloc_bytes(pool, size); case .Free: - return nil, nil; + return nil, .Mode_Not_Implemented; case .Free_All: dynamic_pool_free_all(pool); return nil, nil; @@ -786,7 +785,7 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, nil; case .Query_Info: - return nil, nil; + panic("mem: panic allocator, .Query_Info called"); } return nil, nil; @@ -908,106 +907,9 @@ tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, nil; case .Query_Info: - return nil, nil; + unreachable(); } return result, err; } - - -// Small_Allocator primary allocates memory from its local buffer of size BUFFER_SIZE -// If that buffer's memory is exhausted, it will use the backing allocator (a scratch allocator is recommended) -// Memory allocated with Small_Allocator cannot be freed individually using 'free' and must be freed using 'free_all' -Small_Allocator :: struct($BUFFER_SIZE: int) - where - BUFFER_SIZE >= 2*size_of(uintptr), - BUFFER_SIZE & (BUFFER_SIZE-1) == 0 { - - buffer: [BUFFER_SIZE]byte, - backing: Allocator, - start: uintptr, - curr: uintptr, - end: uintptr, - chunk_size: int, -} - -small_allocator :: proc(s: ^$S/Small_Allocator, backing := context.allocator) -> (a: Allocator) { - if s.backing.procedure == nil { - s.backing = backing; - } - a.data = s; - a.procedure = proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr { - s := (^S)(allocator_data); - if s.chunk_size <= 0 { - s.chunk_size = 4*1024; - } - if s.start == 0 { - s.start = uintptr(&s.buffer[0]); - s.curr = s.start; - s.end = s.start + uintptr(S.BUFFER_SIZE); - (^rawptr)(s.start)^ = nil; - s.curr += size_of(rawptr); - } - - - switch mode { - case .Alloc: - s.curr = align_forward_uintptr(s.curr, uintptr(alignment)); - if size > int(s.end - s.curr) { - to_allocate := size_of(rawptr) + size + alignment; - if to_allocate < s.chunk_size { - to_allocate = s.chunk_size; - } - s.chunk_size *= 2; - - p := alloc(to_allocate, 16, s.backing, loc); - (^rawptr)(s.start)^ = p; - s.start = uintptr(p); - s.curr = s.start; - s.end = s.start + uintptr(to_allocate); - - (^rawptr)(s.start)^ = nil; - s.curr += size_of(rawptr); - s.curr = align_forward_uintptr(s.curr, uintptr(alignment)); - } - - p := rawptr(s.curr); - s.curr += uintptr(size); - return mem_zero(p, size); - - case .Free: - // NOP - return nil; - - case .Resize: - // No need copying the code - return default_resize_align(old_memory, old_size, size, alignment, small_allocator(s, s.backing), loc); - - case .Free_All: - p := (^rawptr)(&s.buffer[0])^; - for p != nil { - next := (^rawptr)(p)^; - free(next, s.backing, loc); - p = next; - } - // Reset to default - s.start = uintptr(&s.buffer[0]); - s.curr = s.start; - s.end = s.start + uintptr(S.BUFFER_SIZE); - - (^rawptr)(s.start)^ = nil; - s.curr += size_of(rawptr); - - - case .Query_Features: - return nil, nil; - - case .Query_Info: - return nil, nil; - } - - return nil, nil; - }; - return a; -} diff --git a/core/os/os.odin b/core/os/os.odin index 6913b9277..c9aa18eb0 100644 --- a/core/os/os.odin +++ b/core/os/os.odin @@ -188,7 +188,7 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, aligned_free(old_memory); case .Free_All: - // NOTE(tetra): Do nothing. + return nil, .Mode_Not_Implemented; case .Resize: if old_memory == nil { @@ -204,7 +204,7 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, return nil, nil; case .Query_Info: - return nil, nil; + return nil, .Mode_Not_Implemented; } return nil, nil; diff --git a/core/os/os2/heap_windows.odin b/core/os/os2/heap_windows.odin index 34f8c6933..25fe660ee 100644 --- a/core/os/os2/heap_windows.odin +++ b/core/os/os2/heap_windows.odin @@ -84,7 +84,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, aligned_free(old_memory); case .Free_All: - // NOTE(tetra): Do nothing. + return nil, .Mode_Not_Implemented; case .Resize: if old_memory == nil { diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 35762f1ae..813fe8c6b 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -276,10 +276,11 @@ Allocator_Query_Info :: struct { } Allocator_Error :: enum byte { - None = 0, - Out_Of_Memory = 1, - Invalid_Pointer = 2, - Invalid_Argument = 3, + None = 0, + Out_Of_Memory = 1, + Invalid_Pointer = 2, + Invalid_Argument = 3, + Mode_Not_Implemented = 4, } Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode, diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index fce247e9b..d03e5d3aa 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -196,6 +196,7 @@ __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #c new_header: Map_Header = header; nm := Raw_Map{}; nm.entries.allocator = m.entries.allocator; + nm.hashes = m.hashes; new_header.m = &nm; c := context; @@ -239,7 +240,6 @@ __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #c } } - delete(m.hashes, m.entries.allocator, loc); free(m.entries.data, m.entries.allocator, loc); header.m^ = nm; }