Merge pull request #3001 from colrdavidson/unsafe_mem

add non-zeroing append and resize
This commit is contained in:
gingerBill
2024-01-17 21:39:27 +00:00
committed by GitHub
13 changed files with 188 additions and 51 deletions
+9
View File
@@ -96,6 +96,15 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment) str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
case .Resize_Non_Zeroed:
format: string
switch la.size_fmt {
case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%d, size=%d, alignment=%d)"
case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%m, size=%m, alignment=%d)"
}
str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
case .Query_Features: case .Query_Features:
str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding) str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding)
context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
+24 -2
View File
@@ -11,6 +11,8 @@ Allocator_Mode :: enum byte {
Free_All, Free_All,
Resize, Resize,
Query_Features, Query_Features,
Alloc_Non_Zeroed,
Resize_Non_Zeroed,
} }
*/ */
@@ -243,12 +245,26 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
res = raw_data(data) res = raw_data(data)
return return
} }
@(require_results)
default_resize_bytes_align_non_zeroed :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
return _default_resize_bytes_align(old_data, new_size, alignment, false, allocator, loc)
}
@(require_results) @(require_results)
default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
return _default_resize_bytes_align(old_data, new_size, alignment, true, allocator, loc)
}
@(require_results)
_default_resize_bytes_align :: #force_inline proc(old_data: []byte, new_size, alignment: int, should_zero: bool, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
old_memory := raw_data(old_data) old_memory := raw_data(old_data)
old_size := len(old_data) old_size := len(old_data)
if old_memory == nil { if old_memory == nil {
return alloc_bytes(new_size, alignment, allocator, loc) if should_zero {
return alloc_bytes(new_size, alignment, allocator, loc)
} else {
return alloc_bytes_non_zeroed(new_size, alignment, allocator, loc)
}
} }
if new_size == 0 { if new_size == 0 {
@@ -260,7 +276,13 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a
return old_data, .None return old_data, .None
} }
new_memory, err := alloc_bytes(new_size, alignment, allocator, loc) new_memory : []byte
err : Allocator_Error
if should_zero {
new_memory, err = alloc_bytes(new_size, alignment, allocator, loc)
} else {
new_memory, err = alloc_bytes_non_zeroed(new_size, alignment, allocator, loc)
}
if new_memory == nil || err != nil { if new_memory == nil || err != nil {
return nil, err return nil, err
} }
+23 -16
View File
@@ -85,13 +85,16 @@ 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:
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 .Resize_Non_Zeroed:
return default_resize_bytes_align_non_zeroed(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena))
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} set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features}
} }
return nil, nil return nil, nil
@@ -259,7 +262,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 +281,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 +409,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 +437,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 +458,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 +568,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 +593,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 +602,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 +652,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 +665,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 +829,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 +965,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)
} }
+1 -1
View File
@@ -288,7 +288,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.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 {
+7 -7
View File
@@ -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
+1
View File
@@ -307,6 +307,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]
+90 -15
View File
@@ -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}
@@ -406,10 +412,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
} }
@@ -420,7 +423,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)
@@ -437,7 +446,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
} }
@@ -454,7 +472,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 {
@@ -470,11 +494,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)
} }
@@ -494,6 +540,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
@@ -638,8 +685,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
} }
@@ -658,7 +704,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
} }
@@ -668,11 +719,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
} }
@@ -692,7 +752,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
} }
@@ -703,6 +768,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.
+1 -1
View File
@@ -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 {
+5 -1
View File
@@ -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)
+1 -1
View File
@@ -19,7 +19,7 @@ when ODIN_DEFAULT_TO_NIL_ALLOCATOR {
case .Free_All: case .Free_All:
return nil, .Mode_Not_Implemented return nil, .Mode_Not_Implemented
case .Resize: case .Resize, .Resize_Non_Zeroed:
data, err = _windows_default_resize(old_memory, old_size, size, alignment) data, err = _windows_default_resize(old_memory, old_size, size, alignment)
case .Query_Features: case .Query_Features:
+23 -4
View File
@@ -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
+1 -1
View File
@@ -511,7 +511,7 @@ cmark_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mod
case .Free_All: case .Free_All:
return nil, .Mode_Not_Implemented return nil, .Mode_Not_Implemented
case .Resize: case .Resize, .Resize_Non_Zeroed:
new_ptr := cmark_alloc.realloc(old_memory, c.size_t(size)) new_ptr := cmark_alloc.realloc(old_memory, c.size_t(size))
res = transmute([]byte)runtime.Raw_Slice{new_ptr, size} res = transmute([]byte)runtime.Raw_Slice{new_ptr, size}
if size > old_size { if size > old_size {
+1 -1
View File
@@ -1774,7 +1774,7 @@ MemAllocatorProc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
MemFree(old_memory) MemFree(old_memory)
return nil, nil return nil, nil
case .Resize: case .Resize, .Resize_Non_Zeroed:
ptr := MemRealloc(old_memory, c.uint(size)) ptr := MemRealloc(old_memory, c.uint(size))
if ptr == nil { if ptr == nil {
err = .Out_Of_Memory err = .Out_Of_Memory