55 lines
1.3 KiB
Odin
55 lines
1.3 KiB
Odin
|
#+private
|
||
|
package nbio
|
||
|
|
||
|
import "core:container/queue"
|
||
|
import "core:mem"
|
||
|
import "core:mem/virtual"
|
||
|
|
||
|
// An object pool where the objects are allocated on a growing arena.
|
||
|
Pool :: struct($T: typeid) {
|
||
|
allocator: mem.Allocator,
|
||
|
arena: virtual.Arena,
|
||
|
objects_allocator: mem.Allocator,
|
||
|
objects: queue.Queue(^T),
|
||
|
num_waiting: int,
|
||
|
}
|
||
|
|
||
|
DEFAULT_STARTING_CAP :: 8
|
||
|
|
||
|
pool_init :: proc(p: ^Pool($T), cap := DEFAULT_STARTING_CAP, allocator := context.allocator) -> mem.Allocator_Error {
|
||
|
virtual.arena_init_growing(&p.arena) or_return
|
||
|
p.objects_allocator = virtual.arena_allocator(&p.arena)
|
||
|
|
||
|
p.allocator = allocator
|
||
|
queue.init(&p.objects, cap, allocator) or_return
|
||
|
for _ in 0 ..< cap {
|
||
|
_ = queue.push_back(&p.objects, new(T, p.objects_allocator)) or_return
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
pool_destroy :: proc(p: ^Pool($T)) {
|
||
|
virtual.arena_destroy(&p.arena)
|
||
|
queue.destroy(&p.objects)
|
||
|
}
|
||
|
|
||
|
pool_get :: proc(p: ^Pool($T)) -> (^T, mem.Allocator_Error) #optional_allocator_error {
|
||
|
p.num_waiting += 1
|
||
|
|
||
|
elem, ok := queue.pop_front_safe(&p.objects)
|
||
|
if !ok {
|
||
|
return new(T, p.objects_allocator)
|
||
|
}
|
||
|
|
||
|
mem.zero_item(elem)
|
||
|
return elem, nil
|
||
|
}
|
||
|
|
||
|
pool_put :: proc(p: ^Pool($T), elem: ^T) -> mem.Allocator_Error {
|
||
|
p.num_waiting -= 1
|
||
|
|
||
|
_, err := queue.push_back(&p.objects, elem)
|
||
|
return err
|
||
|
}
|