diff options
| author | Laytan Laats <laytanlaats@hotmail.com> | 2026-01-13 19:38:10 +0100 |
|---|---|---|
| committer | Laytan Laats <laytanlaats@hotmail.com> | 2026-01-13 19:38:10 +0100 |
| commit | 4ae02aaacf3ccb9791e01fd3d095b9579cf072d8 (patch) | |
| tree | 1a15b0db90c91f79ec582484e4dd0087459a6de4 /core/container | |
| parent | 24ee35af28a49a110861b49c8aa3a0c7b7c9d5d5 (diff) | |
pool: explicit memory ordering and improved destroy
Diffstat (limited to 'core/container')
| -rw-r--r-- | core/container/pool/pool.odin | 23 |
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 } } |