diff --git a/core/sync/extended.odin b/core/sync/extended.odin index 340244eb9..7370d6544 100644 --- a/core/sync/extended.odin +++ b/core/sync/extended.odin @@ -282,7 +282,15 @@ Once :: struct { } // once_do calls the procedure fn if and only if once_do is being called for the first for this instance of Once. -once_do :: proc(o: ^Once, fn: proc()) { +once_do :: proc{ + once_do_without_data, + once_do_without_data_contextless, + once_do_with_data, + once_do_with_data_contextless, +} + +// once_do_without_data calls the procedure fn if and only if once_do_without_data is being called for the first for this instance of Once. +once_do_without_data :: proc(o: ^Once, fn: proc()) { @(cold) do_slow :: proc(o: ^Once, fn: proc()) { guard(&o.m) @@ -292,12 +300,61 @@ once_do :: proc(o: ^Once, fn: proc()) { } } - if atomic_load_explicit(&o.done, .Acquire) == false { do_slow(o, fn) } } +// once_do_without_data calls the procedure fn if and only if once_do_without_data is being called for the first for this instance of Once. +once_do_without_data_contextless :: proc(o: ^Once, fn: proc "contextless" ()) { + @(cold) + do_slow :: proc(o: ^Once, fn: proc "contextless" ()) { + guard(&o.m) + if !o.done { + fn() + atomic_store_explicit(&o.done, true, .Release) + } + } + + if atomic_load_explicit(&o.done, .Acquire) == false { + do_slow(o, fn) + } +} + +// once_do_with_data calls the procedure fn if and only if once_do_with_data is being called for the first for this instance of Once. +once_do_with_data :: proc(o: ^Once, fn: proc(data: rawptr), data: rawptr) { + @(cold) + do_slow :: proc(o: ^Once, fn: proc(data: rawptr), data: rawptr) { + guard(&o.m) + if !o.done { + fn(data) + atomic_store_explicit(&o.done, true, .Release) + } + } + + if atomic_load_explicit(&o.done, .Acquire) == false { + do_slow(o, fn, data) + } +} + +// once_do_with_data_contextless calls the procedure fn if and only if once_do_with_data_contextless is being called for the first for this instance of Once. +once_do_with_data_contextless :: proc "contextless" (o: ^Once, fn: proc "contextless" (data: rawptr), data: rawptr) { + @(cold) + do_slow :: proc "contextless" (o: ^Once, fn: proc "contextless" (data: rawptr), data: rawptr) { + guard(&o.m) + if !o.done { + fn(data) + atomic_store_explicit(&o.done, true, .Release) + } + } + + if atomic_load_explicit(&o.done, .Acquire) == false { + do_slow(o, fn, data) + } +} + + + // A Parker is an associated token which is initially not present: