From a6c93e2c419d0504031aafe35ad957eb5d59f096 Mon Sep 17 00:00:00 2001 From: jakubtomsu <66876057+jakubtomsu@users.noreply.github.com> Date: Thu, 1 Jun 2023 13:42:26 +0200 Subject: [PATCH] Update SOA dynamic array procs to match non-SOA --- core/runtime/core_builtin_soa.odin | 87 ++++++++++++++---------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/core/runtime/core_builtin_soa.odin b/core/runtime/core_builtin_soa.odin index 10f9846a2..ee2a5f2d0 100644 --- a/core/runtime/core_builtin_soa.odin +++ b/core/runtime/core_builtin_soa.odin @@ -145,26 +145,25 @@ make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.al } @(builtin, require_results) -make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T) { +make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error { context.allocator = allocator - reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc) - return + reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc) or_return + return array, nil } @(builtin, require_results) -make_soa_dynamic_array_len :: proc($T: typeid/#soa[dynamic]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T) { +make_soa_dynamic_array_len :: proc($T: typeid/#soa[dynamic]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error { context.allocator = allocator - resize_soa(&array, length, loc) - return + resize_soa(&array, length, loc) or_return + return array, nil } @(builtin, require_results) -make_soa_dynamic_array_len_cap :: proc($T: typeid/#soa[dynamic]$E, #any_int length, capacity: int, allocator := context.allocator, loc := #caller_location) -> (array: T) { +make_soa_dynamic_array_len_cap :: proc($T: typeid/#soa[dynamic]$E, #any_int length, capacity: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error { context.allocator = allocator - if reserve_soa(&array, capacity, loc) { - resize_soa(&array, length, loc) - } - return + reserve_soa(&array, capacity, loc) or_return + resize_soa(&array, length, loc) or_return + return array, nil } @@ -178,27 +177,25 @@ make_soa :: proc{ @builtin -resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> bool { +resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error { if array == nil { - return false - } - if !reserve_soa(array, length, loc) { - return false + return nil } + reserve_soa(array, length, loc) or_return footer := raw_soa_footer(array) footer.len = length - return true + return nil } @builtin -reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> bool { +reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error { if array == nil { - return false + return nil } old_cap := cap(array) if capacity <= old_cap { - return true + return nil } if array.allocator.procedure == nil { @@ -209,7 +206,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo footer := raw_soa_footer(array) if size_of(E) == 0 { footer.cap = capacity - return true + return nil } ti := type_info_of(typeid_of(T)) @@ -240,13 +237,10 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo old_data := (^rawptr)(array)^ - new_bytes, err := array.allocator.procedure( + new_bytes := array.allocator.procedure( array.allocator.data, .Alloc, new_size, max_align, nil, old_size, loc, - ) - if new_bytes == nil || err != nil { - return false - } + ) or_return new_data := raw_data(new_bytes) @@ -271,31 +265,28 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo new_offset += type.size * capacity } - _, err = array.allocator.procedure( + array.allocator.procedure( array.allocator.data, .Free, 0, max_align, old_data, old_size, loc, - ) + ) or_return - return true + return nil } @builtin -append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) { +append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { if array == nil { - return + return 0, nil } - arg_len := 1 - - if cap(array) <= len(array)+arg_len { - cap := 2 * cap(array) + max(8, arg_len) - _ = reserve_soa(array, cap, loc) + if cap(array) <= len(array) + 1 { + cap := 2 * cap(array) + 8 + err = reserve_soa(array, cap, loc) // do not 'or_return' here as it could be a partial success } - arg_len = min(cap(array)-len(array), arg_len) footer := raw_soa_footer(array) - if size_of(E) > 0 && arg_len > 0 { + if size_of(E) > 0 && cap(array)-len(array) > 0 { ti := type_info_of(typeid_of(T)) ti = type_info_base(ti) si := &ti.variant.(Type_Info_Struct) @@ -328,12 +319,14 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat soa_offset += type.size * cap(array) item_offset += type.size } + footer.len += 1 + return 1, err } - footer.len += arg_len + return 0, err } @builtin -append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) { +append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { if array == nil { return } @@ -345,7 +338,7 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l if cap(array) <= len(array)+arg_len { cap := 2 * cap(array) + max(8, arg_len) - _ = reserve_soa(array, cap, loc) + err = reserve_soa(array, cap, loc) // do not 'or_return' here as it could be a partial success } arg_len = min(cap(array)-len(array), arg_len) @@ -382,8 +375,8 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l item_offset += type.size } } - footer.len += arg_len + return arg_len, err } @@ -395,21 +388,23 @@ append_soa :: proc{ } -delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) { +delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { when intrinsics.type_struct_field_count(E) != 0 { array := array ptr := (^rawptr)(&array)^ - free(ptr, allocator, loc) + free(ptr, allocator, loc) or_return } + return nil } -delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) { +delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error { when intrinsics.type_struct_field_count(E) != 0 { array := array ptr := (^rawptr)(&array)^ footer := raw_soa_footer(&array) - free(ptr, footer.allocator, loc) + free(ptr, footer.allocator, loc) or_return } + return nil }