Make ring suitable for 0 initialization
This commit is contained in:
+46
-62
@@ -7,13 +7,13 @@ import "core:fmt"
|
|||||||
ODIN_BOUNDS_CHECK :: !ODIN_NO_BOUNDS_CHECK
|
ODIN_BOUNDS_CHECK :: !ODIN_NO_BOUNDS_CHECK
|
||||||
|
|
||||||
Ring :: struct($E: typeid) {
|
Ring :: struct($E: typeid) {
|
||||||
data: []E,
|
data: []E,
|
||||||
_end_index, len: int,
|
next_write_index, len: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
Ring_Soa :: struct($E: typeid) {
|
Ring_Soa :: struct($E: typeid) {
|
||||||
data: #soa[]E,
|
data: #soa[]E,
|
||||||
_end_index, len: int,
|
next_write_index, len: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy_aos :: #force_inline proc(ring: ^Ring($E)) -> runtime.Allocator_Error {
|
destroy_aos :: #force_inline proc(ring: ^Ring($E)) -> runtime.Allocator_Error {
|
||||||
@@ -38,7 +38,6 @@ create_aos :: #force_inline proc(
|
|||||||
err: runtime.Allocator_Error,
|
err: runtime.Allocator_Error,
|
||||||
) #optional_allocator_error {
|
) #optional_allocator_error {
|
||||||
ring.data, err = make([]E, capacity, allocator)
|
ring.data, err = make([]E, capacity, allocator)
|
||||||
ring._end_index = -1
|
|
||||||
return ring, err
|
return ring, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,21 +50,20 @@ create_soa :: #force_inline proc(
|
|||||||
err: runtime.Allocator_Error,
|
err: runtime.Allocator_Error,
|
||||||
) #optional_allocator_error {
|
) #optional_allocator_error {
|
||||||
ring.data, err = make(#soa[]E, capacity, allocator)
|
ring.data, err = make(#soa[]E, capacity, allocator)
|
||||||
ring._end_index = -1
|
|
||||||
return ring, err
|
return ring, err
|
||||||
}
|
}
|
||||||
|
|
||||||
init_from_slice_aos :: #force_inline proc(ring: ^Ring($E), data: $T/[]E) {
|
init_from_slice_aos :: #force_inline proc(ring: ^Ring($E), data: $T/[]E) {
|
||||||
ring.data = data
|
ring.data = data
|
||||||
ring.len = 0
|
ring.len = 0
|
||||||
ring._end_index = -1
|
ring.next_write_index = 0
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
init_from_slice_soa :: #force_inline proc(ring: ^Ring_Soa($E), data: $T/#soa[]E) {
|
init_from_slice_soa :: #force_inline proc(ring: ^Ring_Soa($E), data: $T/#soa[]E) {
|
||||||
ring.data = data
|
ring.data = data
|
||||||
ring.len = 0
|
ring.len = 0
|
||||||
ring._end_index = -1
|
ring.next_write_index = 0
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,46 +72,32 @@ init_from_slice :: proc {
|
|||||||
init_from_slice_soa,
|
init_from_slice_soa,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal
|
||||||
// Index in the backing array where the ring starts
|
// Index in the backing array where the ring starts
|
||||||
_start_index_aos :: #force_inline proc(ring: Ring($E)) -> int {
|
start_index_aos :: #force_inline proc(ring: Ring($E)) -> int {
|
||||||
if ring.len < len(ring.data) {
|
return ring.len < len(ring.data) ? 0 : ring.next_write_index
|
||||||
return 0
|
|
||||||
} else {
|
|
||||||
start_index := ring._end_index + 1
|
|
||||||
return 0 if start_index == len(ring.data) else start_index
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal
|
||||||
// Index in the backing array where the ring starts
|
// Index in the backing array where the ring starts
|
||||||
_start_index_soa :: #force_inline proc(ring: Ring_Soa($E)) -> int {
|
start_index_soa :: #force_inline proc(ring: Ring_Soa($E)) -> int {
|
||||||
if ring.len < len(ring.data) {
|
return ring.len < len(ring.data) ? 0 : ring.next_write_index
|
||||||
return 0
|
|
||||||
} else {
|
|
||||||
start_index := ring._end_index + 1
|
|
||||||
return 0 if start_index == len(ring.data) else start_index
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
advance_aos :: #force_inline proc(ring: ^Ring($E)) {
|
advance_aos :: #force_inline proc(ring: ^Ring($E)) {
|
||||||
// Length
|
// Length
|
||||||
if ring.len != len(ring.data) do ring.len += 1
|
if ring.len != len(ring.data) do ring.len += 1
|
||||||
// End index
|
// Write index
|
||||||
if ring._end_index == len(ring.data) - 1 { // If we are at the end of the backing array
|
ring.next_write_index += 1
|
||||||
ring._end_index = 0 // Overflow end to 0
|
if ring.next_write_index == len(ring.data) do ring.next_write_index = 0
|
||||||
} else {
|
|
||||||
ring._end_index += 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
advance_soa :: #force_inline proc(ring: ^Ring_Soa($E)) {
|
advance_soa :: #force_inline proc(ring: ^Ring_Soa($E)) {
|
||||||
// Length
|
// Length
|
||||||
if ring.len != len(ring.data) do ring.len += 1
|
if ring.len != len(ring.data) do ring.len += 1
|
||||||
// End index
|
// Write index
|
||||||
if ring._end_index == len(ring.data) - 1 { // If we are at the end of the backing array
|
ring.next_write_index += 1
|
||||||
ring._end_index = 0 // Overflow end to 0
|
if ring.next_write_index == len(ring.data) do ring.next_write_index = 0
|
||||||
} else {
|
|
||||||
ring._end_index += 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
advance :: proc {
|
advance :: proc {
|
||||||
@@ -122,13 +106,13 @@ advance :: proc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
append_aos :: #force_inline proc(ring: ^Ring($E), element: E) {
|
append_aos :: #force_inline proc(ring: ^Ring($E), element: E) {
|
||||||
|
ring.data[ring.next_write_index] = element
|
||||||
advance(ring)
|
advance(ring)
|
||||||
ring.data[ring._end_index] = element
|
|
||||||
}
|
}
|
||||||
|
|
||||||
append_soa :: #force_inline proc(ring: ^Ring_Soa($E), element: E) {
|
append_soa :: #force_inline proc(ring: ^Ring_Soa($E), element: E) {
|
||||||
|
ring.data[ring.next_write_index] = element
|
||||||
advance(ring)
|
advance(ring)
|
||||||
ring.data[ring._end_index] = element
|
|
||||||
}
|
}
|
||||||
|
|
||||||
append :: proc {
|
append :: proc {
|
||||||
@@ -141,7 +125,7 @@ get_aos :: #force_inline proc(ring: Ring($E), index: int) -> ^E {
|
|||||||
fmt.assertf(index < ring.len, "Ring index %i out of bounds for length %i", index, ring.len)
|
fmt.assertf(index < ring.len, "Ring index %i out of bounds for length %i", index, ring.len)
|
||||||
}
|
}
|
||||||
|
|
||||||
array_index := _start_index_aos(ring) + index
|
array_index := start_index_aos(ring) + index
|
||||||
if array_index < len(ring.data) {
|
if array_index < len(ring.data) {
|
||||||
return &ring.data[array_index]
|
return &ring.data[array_index]
|
||||||
} else {
|
} else {
|
||||||
@@ -156,7 +140,7 @@ get_soa :: #force_inline proc(ring: Ring_Soa($E), index: int) -> E {
|
|||||||
fmt.assertf(index < ring.len, "Ring index %i out of bounds for length %i", index, ring.len)
|
fmt.assertf(index < ring.len, "Ring index %i out of bounds for length %i", index, ring.len)
|
||||||
}
|
}
|
||||||
|
|
||||||
array_index := _start_index_soa(ring) + index
|
array_index := start_index_soa(ring) + index
|
||||||
if array_index < len(ring.data) {
|
if array_index < len(ring.data) {
|
||||||
return ring.data[array_index]
|
return ring.data[array_index]
|
||||||
} else {
|
} else {
|
||||||
@@ -185,12 +169,12 @@ get_last :: proc {
|
|||||||
|
|
||||||
clear_aos :: #force_inline proc "contextless" (ring: ^Ring($E)) {
|
clear_aos :: #force_inline proc "contextless" (ring: ^Ring($E)) {
|
||||||
ring.len = 0
|
ring.len = 0
|
||||||
ring._end_index = -1
|
ring.next_write_index = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_soa :: #force_inline proc "contextless" (ring: ^Ring_Soa($E)) {
|
clear_soa :: #force_inline proc "contextless" (ring: ^Ring_Soa($E)) {
|
||||||
ring.len = 0
|
ring.len = 0
|
||||||
ring._end_index = -1
|
ring.next_write_index = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
clear :: proc {
|
clear :: proc {
|
||||||
@@ -212,21 +196,21 @@ test_ring_aos :: proc(t: ^testing.T) {
|
|||||||
for i in 1 ..= 5 {
|
for i in 1 ..= 5 {
|
||||||
append(&ring, i)
|
append(&ring, i)
|
||||||
log.debug("Length:", ring.len)
|
log.debug("Length:", ring.len)
|
||||||
log.debug("Start index:", _start_index_aos(ring))
|
log.debug("Start index:", start_index_aos(ring))
|
||||||
log.debug("End index:", ring._end_index)
|
log.debug("Next write index:", ring.next_write_index)
|
||||||
log.debug(ring.data)
|
log.debug(ring.data)
|
||||||
}
|
}
|
||||||
testing.expect_value(t, get(ring, 0)^, 1)
|
testing.expect_value(t, get(ring, 0)^, 1)
|
||||||
testing.expect_value(t, get(ring, 4)^, 5)
|
testing.expect_value(t, get(ring, 4)^, 5)
|
||||||
testing.expect_value(t, ring.len, 5)
|
testing.expect_value(t, ring.len, 5)
|
||||||
testing.expect_value(t, ring._end_index, 4)
|
testing.expect_value(t, ring.next_write_index, 5)
|
||||||
testing.expect_value(t, _start_index_aos(ring), 0)
|
testing.expect_value(t, start_index_aos(ring), 0)
|
||||||
|
|
||||||
for i in 6 ..= 15 {
|
for i in 6 ..= 15 {
|
||||||
append(&ring, i)
|
append(&ring, i)
|
||||||
log.debug("Length:", ring.len)
|
log.debug("Length:", ring.len)
|
||||||
log.debug("Start index:", _start_index_aos(ring))
|
log.debug("Start index:", start_index_aos(ring))
|
||||||
log.debug("End index:", ring._end_index)
|
log.debug("Next write index:", ring.next_write_index)
|
||||||
log.debug(ring.data)
|
log.debug(ring.data)
|
||||||
}
|
}
|
||||||
testing.expect_value(t, get(ring, 0)^, 6)
|
testing.expect_value(t, get(ring, 0)^, 6)
|
||||||
@@ -234,18 +218,18 @@ test_ring_aos :: proc(t: ^testing.T) {
|
|||||||
testing.expect_value(t, get(ring, 9)^, 15)
|
testing.expect_value(t, get(ring, 9)^, 15)
|
||||||
testing.expect_value(t, get_last(ring)^, 15)
|
testing.expect_value(t, get_last(ring)^, 15)
|
||||||
testing.expect_value(t, ring.len, 10)
|
testing.expect_value(t, ring.len, 10)
|
||||||
testing.expect_value(t, ring._end_index, 4)
|
testing.expect_value(t, ring.next_write_index, 5)
|
||||||
testing.expect_value(t, _start_index_aos(ring), 5)
|
testing.expect_value(t, start_index_aos(ring), 5)
|
||||||
|
|
||||||
for i in 15 ..= 25 {
|
for i in 15 ..= 25 {
|
||||||
append(&ring, i)
|
append(&ring, i)
|
||||||
log.debug("Length:", ring.len)
|
log.debug("Length:", ring.len)
|
||||||
log.debug("Start index:", _start_index_aos(ring))
|
log.debug("Start index:", start_index_aos(ring))
|
||||||
log.debug("End index:", ring._end_index)
|
log.debug("Next write index:", ring.next_write_index)
|
||||||
log.debug(ring.data)
|
log.debug(ring.data)
|
||||||
}
|
}
|
||||||
testing.expect_value(t, get(ring, 0)^, 16)
|
testing.expect_value(t, get(ring, 0)^, 16)
|
||||||
testing.expect_value(t, ring._end_index, 5)
|
testing.expect_value(t, ring.next_write_index, 6)
|
||||||
testing.expect_value(t, get_last(ring)^, 25)
|
testing.expect_value(t, get_last(ring)^, 25)
|
||||||
|
|
||||||
clear(&ring)
|
clear(&ring)
|
||||||
@@ -266,21 +250,21 @@ test_ring_soa :: proc(t: ^testing.T) {
|
|||||||
for i in 1 ..= 5 {
|
for i in 1 ..= 5 {
|
||||||
append(&ring, Ints{i, i})
|
append(&ring, Ints{i, i})
|
||||||
log.debug("Length:", ring.len)
|
log.debug("Length:", ring.len)
|
||||||
log.debug("Start index:", _start_index_soa(ring))
|
log.debug("Start index:", start_index_soa(ring))
|
||||||
log.debug("End index:", ring._end_index)
|
log.debug("Next write index:", ring.next_write_index)
|
||||||
log.debug(ring.data)
|
log.debug(ring.data)
|
||||||
}
|
}
|
||||||
testing.expect_value(t, get(ring, 0), Ints{1, 1})
|
testing.expect_value(t, get(ring, 0), Ints{1, 1})
|
||||||
testing.expect_value(t, get(ring, 4), Ints{5, 5})
|
testing.expect_value(t, get(ring, 4), Ints{5, 5})
|
||||||
testing.expect_value(t, ring.len, 5)
|
testing.expect_value(t, ring.len, 5)
|
||||||
testing.expect_value(t, ring._end_index, 4)
|
testing.expect_value(t, ring.next_write_index, 5)
|
||||||
testing.expect_value(t, _start_index_soa(ring), 0)
|
testing.expect_value(t, start_index_soa(ring), 0)
|
||||||
|
|
||||||
for i in 6 ..= 15 {
|
for i in 6 ..= 15 {
|
||||||
append(&ring, Ints{i, i})
|
append(&ring, Ints{i, i})
|
||||||
log.debug("Length:", ring.len)
|
log.debug("Length:", ring.len)
|
||||||
log.debug("Start index:", _start_index_soa(ring))
|
log.debug("Start index:", start_index_soa(ring))
|
||||||
log.debug("End index:", ring._end_index)
|
log.debug("Next write index:", ring.next_write_index)
|
||||||
log.debug(ring.data)
|
log.debug(ring.data)
|
||||||
}
|
}
|
||||||
testing.expect_value(t, get(ring, 0), Ints{6, 6})
|
testing.expect_value(t, get(ring, 0), Ints{6, 6})
|
||||||
@@ -288,18 +272,18 @@ test_ring_soa :: proc(t: ^testing.T) {
|
|||||||
testing.expect_value(t, get(ring, 9), Ints{15, 15})
|
testing.expect_value(t, get(ring, 9), Ints{15, 15})
|
||||||
testing.expect_value(t, get_last(ring), Ints{15, 15})
|
testing.expect_value(t, get_last(ring), Ints{15, 15})
|
||||||
testing.expect_value(t, ring.len, 10)
|
testing.expect_value(t, ring.len, 10)
|
||||||
testing.expect_value(t, ring._end_index, 4)
|
testing.expect_value(t, ring.next_write_index, 5)
|
||||||
testing.expect_value(t, _start_index_soa(ring), 5)
|
testing.expect_value(t, start_index_soa(ring), 5)
|
||||||
|
|
||||||
for i in 15 ..= 25 {
|
for i in 15 ..= 25 {
|
||||||
append(&ring, Ints{i, i})
|
append(&ring, Ints{i, i})
|
||||||
log.debug("Length:", ring.len)
|
log.debug("Length:", ring.len)
|
||||||
log.debug("Start index:", _start_index_soa(ring))
|
log.debug("Start index:", start_index_soa(ring))
|
||||||
log.debug("End index:", ring._end_index)
|
log.debug("Next write index:", ring.next_write_index)
|
||||||
log.debug(ring.data)
|
log.debug(ring.data)
|
||||||
}
|
}
|
||||||
testing.expect_value(t, get(ring, 0), Ints{16, 16})
|
testing.expect_value(t, get(ring, 0), Ints{16, 16})
|
||||||
testing.expect_value(t, ring._end_index, 5)
|
testing.expect_value(t, ring.next_write_index, 6)
|
||||||
testing.expect_value(t, get_last(ring), Ints{25, 25})
|
testing.expect_value(t, get_last(ring), Ints{25, 25})
|
||||||
|
|
||||||
clear(&ring)
|
clear(&ring)
|
||||||
|
|||||||
Reference in New Issue
Block a user