-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerational_array.odin
More file actions
101 lines (86 loc) · 2.25 KB
/
Copy pathgenerational_array.odin
File metadata and controls
101 lines (86 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#+private
package glodin
import "base:runtime"
Index :: u32
_Index :: bit_field u32 {
index: u16 | 16,
generation: u16 | 15,
}
@(private = "file")
Generational_Array_Elem :: struct($T: typeid) {
value: T,
id: bit_field u16 {
generation: u16 | 15,
alive: bool | 1,
},
location: (runtime.Source_Code_Location when GLODIN_TRACK_LEAKS else struct{}),
}
Generational_Array :: struct($T: typeid) {
data: #soa[max(u16)]Generational_Array_Elem(T) `fmt:"-"`,
len: int,
free: [dynamic]u16,
}
ga_append :: proc(ga: ^Generational_Array($T), val: T, location: runtime.Source_Code_Location) -> (index: Index) {
assert(ga != nil)
_index: _Index
if idx, ok := pop_safe(&ga.free); ok {
ga.data[idx].value = val
ga.data[idx].id.alive = true
_index.index = u16(idx)
ga.data[idx].id.generation += 1
if ga.data[idx].id.generation == 0 {
ga.data[idx].id.generation = 1
}
_index.generation = ga.data[idx].id.generation
return Index(_index)
}
_index.index = u16(ga.len)
_index.generation = 1
ga.data[ga.len] = {
value = val,
id = {generation = 1, alive = true},
}
when GLODIN_TRACK_LEAKS {
ga.data[ga.len].location = location
}
ga.len += 1
return Index(_index)
}
ga_remove :: proc(ga: ^Generational_Array($T), index: $I/Index) {
assert(ga != nil)
index := _Index(index)
assert(int(index.index) < len(ga.data))
id := &ga.data[index.index].id
assert(id.generation == index.generation && index.generation != 0 && id.alive)
id.alive = false
append(&ga.free, u16(index.index))
}
ga_get :: proc(ga: ^Generational_Array($T), index: $I/Index) -> ^T {
assert(ga != nil)
index := _Index(index)
if len(ga.data) > int(index.index) {
id := ga.data[index.index].id
if id.generation == index.generation && id.alive && id.generation != 0 {
return &ga.data[index.index].value
} else {
return nil
}
} else {
error(len(ga.data), int(index.index))
return nil
}
}
ga_iter :: proc(ga: ^Generational_Array($T), iter: ^int) -> (elem: T, index: Index, cond: bool) {
assert(ga != nil)
assert(iter != nil)
for iter^ < ga.len {
defer iter^ += 1
if ga.data[iter^].id.alive {
elem = ga.data[iter^].value
index = Index(_Index{index = u16(iter^), generation = ga.data[iter^].id.generation})
cond = true
break
}
}
return
}