aboutsummaryrefslogtreecommitdiff
path: root/core/container
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2026-01-13 19:38:10 +0100
committerLaytan Laats <laytanlaats@hotmail.com>2026-01-13 19:38:10 +0100
commit4ae02aaacf3ccb9791e01fd3d095b9579cf072d8 (patch)
tree1a15b0db90c91f79ec582484e4dd0087459a6de4 /core/container
parent24ee35af28a49a110861b49c8aa3a0c7b7c9d5d5 (diff)
pool: explicit memory ordering and improved destroy
Diffstat (limited to 'core/container')
-rw-r--r--core/container/pool/pool.odin23
1 files changed, 15 insertions, 8 deletions
diff --git a/core/container/pool/pool.odin b/core/container/pool/pool.odin
index 93eddb514..d3e815351 100644
--- a/core/container/pool/pool.odin
+++ b/core/container/pool/pool.odin
@@ -41,26 +41,33 @@ init :: proc(p: ^Pool($T), $link_field: string, block_size: uint = DEFAULT_BLOCK
}
destroy :: proc(p: ^Pool($T)) {
- for elem := p.free_list; elem != nil; elem = _get_next(p, elem) {
- _unpoison_elem(p, elem)
- free(elem, _pool_arena_allocator(&p.arena))
+ elem := sync.atomic_exchange_explicit(&p.free_list, nil, .Acquire)
+
+ sync.atomic_store_explicit(&p.num_ready, 0, .Relaxed)
+ assert(sync.atomic_load_explicit(&p.num_outstanding, .Relaxed) == 0)
+
+ when .Address in ODIN_SANITIZER_FLAGS {
+ for ; elem != nil; elem = _get_next(p, elem) {
+ _unpoison_elem(p, elem)
+ }
}
_pool_arena_destroy(&p.arena)
+ p.arena = {}
}
@(require_results)
get :: proc(p: ^Pool($T)) -> (elem: ^T, err: mem.Allocator_Error) #optional_allocator_error {
- sync.atomic_add_explicit(&p.num_outstanding, 1, .Relaxed)
+ defer sync.atomic_add_explicit(&p.num_outstanding, 1, .Relaxed)
for {
- elem = sync.atomic_load(&p.free_list)
+ elem = sync.atomic_load_explicit(&p.free_list, .Acquire)
if elem == nil {
// NOTE: pool arena has an internal lock.
return new(T, _pool_arena_allocator(&p.arena))
}
- if _, ok := sync.atomic_compare_exchange_weak(&p.free_list, elem, _get_next(p, elem)); ok {
+ if _, ok := sync.atomic_compare_exchange_weak_explicit(&p.free_list, elem, _get_next(p, elem), .Acquire, .Relaxed); ok {
_set_next(p, elem, nil)
_unpoison_elem(p, elem)
sync.atomic_sub_explicit(&p.num_ready, 1, .Relaxed)
@@ -77,9 +84,9 @@ put :: proc(p: ^Pool($T), elem: ^T) {
defer sync.atomic_add_explicit(&p.num_ready, 1, .Relaxed)
for {
- head := sync.atomic_load(&p.free_list)
+ head := sync.atomic_load_explicit(&p.free_list, .Relaxed)
_set_next(p, elem, head)
- if _, ok := sync.atomic_compare_exchange_weak(&p.free_list, head, elem); ok {
+ if _, ok := sync.atomic_compare_exchange_weak_explicit(&p.free_list, head, elem, .Release, .Relaxed); ok {
return
}
}