Browse Source

Merge pull request #2571 from jakubtomsu/builtin-soa-procs-improvements

Update SOA dynamic array procs to match non-SOA
gingerBill 2 years ago
parent
commit
6a2ff3a371
1 changed files with 41 additions and 46 deletions
  1. 41 46
      core/runtime/core_builtin_soa.odin

+ 41 - 46
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)
 @(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
 	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)
 @(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
 	context.allocator = allocator
-	resize_soa(&array, length, loc)
-	return
+	resize_soa(&array, length, loc) or_return
+	return array, nil
 }
 }
 
 
 @(builtin, require_results)
 @(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
 	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
 @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 {
 	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 := raw_soa_footer(array)
 	footer.len = length
 	footer.len = length
-	return true
+	return nil
 }
 }
 
 
 @builtin
 @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 {
 	if array == nil {
-		return false
+		return nil
 	}
 	}
 
 
 	old_cap := cap(array)
 	old_cap := cap(array)
 	if capacity <= old_cap {
 	if capacity <= old_cap {
-		return true
+		return nil
 	}
 	}
 
 
 	if array.allocator.procedure == 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)
 	footer := raw_soa_footer(array)
 	if size_of(E) == 0 {
 	if size_of(E) == 0 {
 		footer.cap = capacity
 		footer.cap = capacity
-		return true
+		return nil
 	}
 	}
 
 
 	ti := type_info_of(typeid_of(T))
 	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)^
 	old_data := (^rawptr)(array)^
 
 
-	new_bytes, err := array.allocator.procedure(
+	new_bytes := array.allocator.procedure(
 		array.allocator.data, .Alloc, new_size, max_align,
 		array.allocator.data, .Alloc, new_size, max_align,
 		nil, old_size, loc,
 		nil, old_size, loc,
-	)
-	if new_bytes == nil || err != nil {
-		return false
-	}
+	) or_return
 	new_data := raw_data(new_bytes)
 	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
 		new_offset += type.size * capacity
 	}
 	}
 
 
-	_, err = array.allocator.procedure(
+	array.allocator.procedure(
 		array.allocator.data, .Free, 0, max_align,
 		array.allocator.data, .Free, 0, max_align,
 		old_data, old_size, loc,
 		old_data, old_size, loc,
-	)
+	) or_return
 
 
-	return true
+	return nil
 }
 }
 
 
 @builtin
 @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 {
 	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)
 	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_of(typeid_of(T))
 		ti = type_info_base(ti)
 		ti = type_info_base(ti)
 		si := &ti.variant.(Type_Info_Struct)
 		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)
 			soa_offset  += type.size * cap(array)
 			item_offset += type.size
 			item_offset += type.size
 		}
 		}
+		footer.len += 1
+		return 1, err
 	}
 	}
-	footer.len += arg_len
+	return 0, err
 }
 }
 
 
 @builtin
 @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 {
 	if array == nil {
 		return
 		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 {
 	if cap(array) <= len(array)+arg_len {
 		cap := 2 * cap(array) + max(8, 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)
 	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
 			item_offset += type.size
 		}
 		}
 	}
 	}
-
 	footer.len += arg_len
 	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 {
 	when intrinsics.type_struct_field_count(E) != 0 {
 		array := array
 		array := array
 		ptr := (^rawptr)(&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 {
 	when intrinsics.type_struct_field_count(E) != 0 {
 		array := array
 		array := array
 		ptr := (^rawptr)(&array)^
 		ptr := (^rawptr)(&array)^
 		footer := raw_soa_footer(&array)
 		footer := raw_soa_footer(&array)
-		free(ptr, footer.allocator, loc)
+		free(ptr, footer.allocator, loc) or_return
 	}
 	}
+	return nil
 }
 }