2025-01-13 02:46:54 +04:00

82 lines
1.5 KiB
Odin

package spanpool
import "core:slice"
Element :: struct($E: typeid) {
value: $T,
gen: i32,
}
Span :: struct {
first, len: i32,
}
Span_Pool :: struct($E: typeid) {
elems: [dynamic]Element(E),
free_spans: [dynamic]Span,
}
Handle :: struct {
first: i32,
len: i32,
gen: i32,
}
allocate :: proc(s: ^$T/Span_Pool($E), elems: []T) -> (handle: Handle) {
handle = _allocate(s, len(elems))
for i in 0..<handle.len {
s.elems[i + handle.first].value = elems[i]
}
}
_allocate :: proc(s: ^$T/Span_Pool($E), count: i32) -> (handle: Handle) {
handle.len = count
maybe_existing_span: Maybe(i32)
for span, i in s.free_spans {
if span.len >= count {
maybe_existing_span = i
break
}
}
existing_span, ok := maybe_existing_span.?
if ok {
span := s.free_spans[existing_span]
handle.first = span.first
new_len := span.len - count
if new_len == 0 {
ordered_remove(&s.free_spans, existing_span)
} else {
s.free_spans[existing_span].first += count
s.free_spans[existing_span].len = new_len
}
} else {
handle.first = len(s.elems)
resize(&s.elems, len(s.elems) + count)
}
// Now figure out the generation index
max_gen := 0
for i in handle.first..<handle.first + handle.len {
gen = max(s.elems[i].gen)
}
handle.gen = max_gen + 1
for i in handle.first..<handle.first + handle.len {
s.elems[i].gen = handle.gen
}
return
}
free :: proc(s: ^$T/Span_Pool($E), handle: Handle) {
append(&s.free_spans, Span{first = handle.first, len = handle.len})
}
reconcile :: proc(s: ^$T/Span_Pool($E)) {
}