mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
add non-zeroing append and resize
This commit is contained in:
@@ -11,6 +11,8 @@ Allocator_Mode :: enum byte {
|
|||||||
Free_All,
|
Free_All,
|
||||||
Resize,
|
Resize,
|
||||||
Query_Features,
|
Query_Features,
|
||||||
|
Alloc_Non_Zeroed,
|
||||||
|
Resize_Non_Zeroed,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+18
-14
@@ -85,7 +85,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
case .Free_All:
|
case .Free_All:
|
||||||
arena.offset = 0
|
arena.offset = 0
|
||||||
|
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
return default_resize_bytes_align(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena))
|
return default_resize_bytes_align(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena))
|
||||||
|
|
||||||
case .Query_Features:
|
case .Query_Features:
|
||||||
@@ -259,7 +259,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
}
|
}
|
||||||
clear(&s.leaked_allocations)
|
clear(&s.leaked_allocations)
|
||||||
|
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
begin := uintptr(raw_data(s.data))
|
begin := uintptr(raw_data(s.data))
|
||||||
end := begin + uintptr(len(s.data))
|
end := begin + uintptr(len(s.data))
|
||||||
old_ptr := uintptr(old_memory)
|
old_ptr := uintptr(old_memory)
|
||||||
@@ -278,7 +278,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
case .Query_Features:
|
case .Query_Features:
|
||||||
set := (^Allocator_Mode_Set)(old_memory)
|
set := (^Allocator_Mode_Set)(old_memory)
|
||||||
if set != nil {
|
if set != nil {
|
||||||
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features}
|
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
@@ -406,9 +406,9 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
s.prev_offset = 0
|
s.prev_offset = 0
|
||||||
s.curr_offset = 0
|
s.curr_offset = 0
|
||||||
|
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
if old_memory == nil {
|
if old_memory == nil {
|
||||||
return raw_alloc(s, size, alignment, true)
|
return raw_alloc(s, size, alignment, mode == .Resize)
|
||||||
}
|
}
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -434,7 +434,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data)))
|
old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data)))
|
||||||
|
|
||||||
if old_offset != header.prev_offset {
|
if old_offset != header.prev_offset {
|
||||||
data, err := raw_alloc(s, size, alignment, true)
|
data, err := raw_alloc(s, size, alignment, mode == .Resize)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
runtime.copy(data, byte_slice(old_memory, old_size))
|
runtime.copy(data, byte_slice(old_memory, old_size))
|
||||||
}
|
}
|
||||||
@@ -455,7 +455,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
case .Query_Features:
|
case .Query_Features:
|
||||||
set := (^Allocator_Mode_Set)(old_memory)
|
set := (^Allocator_Mode_Set)(old_memory)
|
||||||
if set != nil {
|
if set != nil {
|
||||||
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features}
|
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
case .Query_Info:
|
case .Query_Info:
|
||||||
@@ -565,9 +565,9 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
case .Free_All:
|
case .Free_All:
|
||||||
s.offset = 0
|
s.offset = 0
|
||||||
|
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
if old_memory == nil {
|
if old_memory == nil {
|
||||||
return raw_alloc(s, size, align, true)
|
return raw_alloc(s, size, align, mode == .Resize)
|
||||||
}
|
}
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -590,7 +590,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
return byte_slice(old_memory, size), nil
|
return byte_slice(old_memory, size), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := raw_alloc(s, size, align, true)
|
data, err := raw_alloc(s, size, align, mode == .Resize)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
runtime.copy(data, byte_slice(old_memory, old_size))
|
runtime.copy(data, byte_slice(old_memory, old_size))
|
||||||
}
|
}
|
||||||
@@ -599,7 +599,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
case .Query_Features:
|
case .Query_Features:
|
||||||
set := (^Allocator_Mode_Set)(old_memory)
|
set := (^Allocator_Mode_Set)(old_memory)
|
||||||
if set != nil {
|
if set != nil {
|
||||||
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features}
|
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
@@ -649,7 +649,7 @@ dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode
|
|||||||
case .Free_All:
|
case .Free_All:
|
||||||
dynamic_pool_free_all(pool)
|
dynamic_pool_free_all(pool)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
if old_size >= size {
|
if old_size >= size {
|
||||||
return byte_slice(old_memory, size), nil
|
return byte_slice(old_memory, size), nil
|
||||||
}
|
}
|
||||||
@@ -662,7 +662,7 @@ dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode
|
|||||||
case .Query_Features:
|
case .Query_Features:
|
||||||
set := (^Allocator_Mode_Set)(old_memory)
|
set := (^Allocator_Mode_Set)(old_memory)
|
||||||
if set != nil {
|
if set != nil {
|
||||||
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Query_Features, .Query_Info}
|
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features, .Query_Info}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
@@ -826,6 +826,10 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
if size > 0 {
|
if size > 0 {
|
||||||
panic("mem: panic allocator, .Resize called", loc=loc)
|
panic("mem: panic allocator, .Resize called", loc=loc)
|
||||||
}
|
}
|
||||||
|
case .Resize_Non_Zeroed:
|
||||||
|
if size > 0 {
|
||||||
|
panic("mem: panic allocator, .Resize_Non_Zeroed called", loc=loc)
|
||||||
|
}
|
||||||
case .Free:
|
case .Free:
|
||||||
if old_memory != nil {
|
if old_memory != nil {
|
||||||
panic("mem: panic allocator, .Free called", loc=loc)
|
panic("mem: panic allocator, .Free called", loc=loc)
|
||||||
@@ -958,7 +962,7 @@ tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
if data.clear_on_free_all {
|
if data.clear_on_free_all {
|
||||||
clear_map(&data.allocation_map)
|
clear_map(&data.allocation_map)
|
||||||
}
|
}
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
if old_memory != result_ptr {
|
if old_memory != result_ptr {
|
||||||
delete_key(&data.allocation_map, old_memory)
|
delete_key(&data.allocation_map, old_memory)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -210,15 +210,15 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> (new_memory: []byte, err: mem.Allocator_Error) {
|
aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int, zero_memory := true) -> (new_memory: []byte, err: mem.Allocator_Error) {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
new_memory = aligned_alloc(new_size, new_alignment, p) or_return
|
new_memory = aligned_alloc(new_size, new_alignment, p, zero_memory) or_return
|
||||||
|
|
||||||
// NOTE: heap_resize does not zero the new memory, so we do it
|
// NOTE: heap_resize does not zero the new memory, so we do it
|
||||||
if new_size > old_size {
|
if zero_memory && new_size > old_size {
|
||||||
new_region := mem.raw_data(new_memory[old_size:])
|
new_region := mem.raw_data(new_memory[old_size:])
|
||||||
mem.zero(new_region, new_size - old_size)
|
mem.zero(new_region, new_size - old_size)
|
||||||
}
|
}
|
||||||
@@ -235,16 +235,16 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
|||||||
case .Free_All:
|
case .Free_All:
|
||||||
return nil, .Mode_Not_Implemented
|
return nil, .Mode_Not_Implemented
|
||||||
|
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
if old_memory == nil {
|
if old_memory == nil {
|
||||||
return aligned_alloc(size, alignment)
|
return aligned_alloc(size, alignment, nil, mode == .Resize)
|
||||||
}
|
}
|
||||||
return aligned_resize(old_memory, old_size, size, alignment)
|
return aligned_resize(old_memory, old_size, size, alignment, mode == .Resize)
|
||||||
|
|
||||||
case .Query_Features:
|
case .Query_Features:
|
||||||
set := (^mem.Allocator_Mode_Set)(old_memory)
|
set := (^mem.Allocator_Mode_Set)(old_memory)
|
||||||
if set != nil {
|
if set != nil {
|
||||||
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Query_Features}
|
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Resize_Non_Zeroed, .Query_Features}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
|
|||||||
@@ -306,6 +306,7 @@ Allocator_Mode :: enum byte {
|
|||||||
Query_Features,
|
Query_Features,
|
||||||
Query_Info,
|
Query_Info,
|
||||||
Alloc_Non_Zeroed,
|
Alloc_Non_Zeroed,
|
||||||
|
Resize_Non_Zeroed,
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocator_Mode_Set :: distinct bit_set[Allocator_Mode]
|
Allocator_Mode_Set :: distinct bit_set[Allocator_Mode]
|
||||||
|
|||||||
@@ -169,10 +169,16 @@ clear :: proc{clear_dynamic_array, clear_map}
|
|||||||
@builtin
|
@builtin
|
||||||
reserve :: proc{reserve_dynamic_array, reserve_map}
|
reserve :: proc{reserve_dynamic_array, reserve_map}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
non_zero_reserve :: proc{non_zero_reserve_dynamic_array}
|
||||||
|
|
||||||
// `resize` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
|
// `resize` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
|
||||||
@builtin
|
@builtin
|
||||||
resize :: proc{resize_dynamic_array}
|
resize :: proc{resize_dynamic_array}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
non_zero_resize :: proc{non_zero_resize_dynamic_array}
|
||||||
|
|
||||||
// Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
|
// Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
|
||||||
@builtin
|
@builtin
|
||||||
shrink :: proc{shrink_dynamic_array, shrink_map}
|
shrink :: proc{shrink_dynamic_array, shrink_map}
|
||||||
@@ -404,10 +410,7 @@ delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_append_elem :: #force_inline proc(array: ^$T/[dynamic]$E, arg: E, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
|
|
||||||
@builtin
|
|
||||||
append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
|
||||||
if array == nil {
|
if array == nil {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
@@ -418,7 +421,13 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) ->
|
|||||||
} else {
|
} else {
|
||||||
if cap(array) < len(array)+1 {
|
if cap(array) < len(array)+1 {
|
||||||
cap := 2 * cap(array) + max(8, 1)
|
cap := 2 * cap(array) + max(8, 1)
|
||||||
err = reserve(array, cap, loc) // do not 'or_return' here as it could be a partial success
|
|
||||||
|
// do not 'or_return' here as it could be a partial success
|
||||||
|
if should_zero {
|
||||||
|
err = reserve(array, cap, loc)
|
||||||
|
} else {
|
||||||
|
err = non_zero_reserve(array, cap, loc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if cap(array)-len(array) > 0 {
|
if cap(array)-len(array) > 0 {
|
||||||
a := (^Raw_Dynamic_Array)(array)
|
a := (^Raw_Dynamic_Array)(array)
|
||||||
@@ -435,7 +444,16 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
|
return _append_elem(array, arg, true, loc=loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
|
return _append_elem(array, arg, false, loc=loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
_append_elems :: #force_inline proc(array: ^$T/[dynamic]$E, should_zero: bool, loc := #caller_location, args: ..E) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
if array == nil {
|
if array == nil {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
@@ -452,7 +470,13 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
|
|||||||
} else {
|
} else {
|
||||||
if cap(array) < len(array)+arg_len {
|
if cap(array) < len(array)+arg_len {
|
||||||
cap := 2 * cap(array) + max(8, arg_len)
|
cap := 2 * cap(array) + max(8, arg_len)
|
||||||
err = reserve(array, cap, loc) // do not 'or_return' here as it could be a partial success
|
|
||||||
|
// do not 'or_return' here as it could be a partial success
|
||||||
|
if should_zero {
|
||||||
|
err = reserve(array, cap, loc)
|
||||||
|
} else {
|
||||||
|
err = non_zero_reserve(array, cap, loc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
arg_len = min(cap(array)-len(array), arg_len)
|
arg_len = min(cap(array)-len(array), arg_len)
|
||||||
if arg_len > 0 {
|
if arg_len > 0 {
|
||||||
@@ -468,11 +492,33 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
|
return _append_elems(array, true, loc, ..args)
|
||||||
|
}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
|
return _append_elems(array, false, loc, ..args)
|
||||||
|
}
|
||||||
|
|
||||||
// The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type
|
// The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type
|
||||||
|
_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
|
args := transmute([]E)arg
|
||||||
|
if should_zero {
|
||||||
|
return append_elems(array, ..args, loc=loc)
|
||||||
|
} else {
|
||||||
|
return non_zero_append_elems(array, ..args, loc=loc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
args := transmute([]E)arg
|
return _append_elem_string(array, arg, true, loc)
|
||||||
return append_elems(array, ..args, loc=loc)
|
}
|
||||||
|
@builtin
|
||||||
|
non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
|
return _append_elem_string(array, arg, false, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -492,6 +538,7 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
|
|||||||
|
|
||||||
// The append built-in procedure appends elements to the end of a dynamic array
|
// The append built-in procedure appends elements to the end of a dynamic array
|
||||||
@builtin append :: proc{append_elem, append_elems, append_elem_string}
|
@builtin append :: proc{append_elem, append_elems, append_elem_string}
|
||||||
|
@builtin non_zero_append :: proc{non_zero_append_elem, non_zero_append_elems, non_zero_append_elem_string}
|
||||||
|
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
@@ -633,8 +680,7 @@ clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) {
|
|||||||
// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
||||||
//
|
//
|
||||||
// Note: Prefer the procedure group `reserve`.
|
// Note: Prefer the procedure group `reserve`.
|
||||||
@builtin
|
_reserve_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
|
||||||
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
|
|
||||||
if array == nil {
|
if array == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -653,7 +699,12 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
|
|||||||
new_size := capacity * size_of(E)
|
new_size := capacity * size_of(E)
|
||||||
allocator := a.allocator
|
allocator := a.allocator
|
||||||
|
|
||||||
new_data := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
|
new_data: []byte
|
||||||
|
if should_zero {
|
||||||
|
new_data = mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
|
||||||
|
} else {
|
||||||
|
new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
|
||||||
|
}
|
||||||
if new_data == nil && new_size > 0 {
|
if new_data == nil && new_size > 0 {
|
||||||
return .Out_Of_Memory
|
return .Out_Of_Memory
|
||||||
}
|
}
|
||||||
@@ -663,11 +714,20 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||||
|
return _reserve_dynamic_array(array, capacity, true, loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||||
|
return _reserve_dynamic_array(array, capacity, false, loc)
|
||||||
|
}
|
||||||
|
|
||||||
// `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
|
// `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
|
||||||
//
|
//
|
||||||
// Note: Prefer the procedure group `resize`
|
// Note: Prefer the procedure group `resize`
|
||||||
@builtin
|
_resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
|
||||||
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
|
|
||||||
if array == nil {
|
if array == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -687,7 +747,12 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller
|
|||||||
new_size := length * size_of(E)
|
new_size := length * size_of(E)
|
||||||
allocator := a.allocator
|
allocator := a.allocator
|
||||||
|
|
||||||
new_data := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
|
new_data : []byte
|
||||||
|
if should_zero {
|
||||||
|
new_data = mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
|
||||||
|
} else {
|
||||||
|
new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
|
||||||
|
}
|
||||||
if new_data == nil && new_size > 0 {
|
if new_data == nil && new_size > 0 {
|
||||||
return .Out_Of_Memory
|
return .Out_Of_Memory
|
||||||
}
|
}
|
||||||
@@ -698,6 +763,16 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
|
||||||
|
return _resize_dynamic_array(array, length, true, loc=loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
@builtin
|
||||||
|
non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
|
||||||
|
return _resize_dynamic_array(array, length, false, loc=loc)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
|
Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
err = .Mode_Not_Implemented
|
err = .Mode_Not_Implemented
|
||||||
case .Free_All:
|
case .Free_All:
|
||||||
arena_free_all(arena, location)
|
arena_free_all(arena, location)
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
old_data := ([^]byte)(old_memory)
|
old_data := ([^]byte)(old_memory)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
return nil, .None
|
return nil, .None
|
||||||
case .Free_All:
|
case .Free_All:
|
||||||
return nil, .Mode_Not_Implemented
|
return nil, .Mode_Not_Implemented
|
||||||
case .Resize:
|
case .Resize, .Resize_Non_Zeroed:
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return nil, .None
|
return nil, .None
|
||||||
}
|
}
|
||||||
@@ -55,6 +55,10 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
if size > 0 {
|
if size > 0 {
|
||||||
panic("panic allocator, .Resize called", loc=loc)
|
panic("panic allocator, .Resize called", loc=loc)
|
||||||
}
|
}
|
||||||
|
case .Resize_Non_Zeroed:
|
||||||
|
if size > 0 {
|
||||||
|
panic("panic allocator, .Alloc_Non_Zeroed called", loc=loc)
|
||||||
|
}
|
||||||
case .Free:
|
case .Free:
|
||||||
if old_memory != nil {
|
if old_memory != nil {
|
||||||
panic("panic allocator, .Free called", loc=loc)
|
panic("panic allocator, .Free called", loc=loc)
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
_mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||||
if allocator.procedure == nil {
|
if allocator.procedure == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -198,15 +198,27 @@ mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAUL
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else if ptr == nil {
|
} else if ptr == nil {
|
||||||
return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
if should_zero {
|
||||||
|
return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
||||||
|
} else {
|
||||||
|
return allocator.procedure(allocator.data, .Alloc_Non_Zeroed, new_size, alignment, nil, 0, loc)
|
||||||
|
}
|
||||||
} else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 {
|
} else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 {
|
||||||
data = ([^]byte)(ptr)[:old_size]
|
data = ([^]byte)(ptr)[:old_size]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
|
if should_zero {
|
||||||
|
data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
|
||||||
|
} else {
|
||||||
|
data, err = allocator.procedure(allocator.data, .Resize_Non_Zeroed, new_size, alignment, ptr, old_size, loc)
|
||||||
|
}
|
||||||
if err == .Mode_Not_Implemented {
|
if err == .Mode_Not_Implemented {
|
||||||
data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
if should_zero {
|
||||||
|
data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
||||||
|
} else {
|
||||||
|
data, err = allocator.procedure(allocator.data, .Alloc_Non_Zeroed, new_size, alignment, nil, 0, loc)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -216,6 +228,13 @@ mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAUL
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||||
|
return _mem_resize(ptr, old_size, new_size, alignment, allocator, true, loc)
|
||||||
|
}
|
||||||
|
non_zero_mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||||
|
return _mem_resize(ptr, old_size, new_size, alignment, allocator, false, loc)
|
||||||
|
}
|
||||||
|
|
||||||
memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
|
memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
|
||||||
switch {
|
switch {
|
||||||
case n == 0: return true
|
case n == 0: return true
|
||||||
|
|||||||
Reference in New Issue
Block a user