3 ms·
My only major objection to C++ magic statics is that you can only use them for statics. Sometimes you find yourself with a task that needs to be done once per
by mtklein 3y ago
My only major objection to C++ magic statics is that you can only use them for statics. Sometimes you find yourself with a task that needs to be done once per object instead of globally, and you've got to roll your own, and then you might as well use that same mechanism for globals too.
My minor objection to magic statics is that you don't have control over the size or packing of the control word, and it usually ends up being something awkwardly mid-sized like a size_t where normally you'd want it either as small as possible or cache-line sized.
I like to handle this something like this:
void once(char _Atomic *flag, void (*fn)(void *ctx), void *ctx) {
char st = atomic_load_explicit(flag, memory_order_acquire);
if (st == 0 && atomic_compare_exchange_strong_explicit(flag, &st, 1,
memory_order_acquire,
memory_order_acquire)) {
fn(ctx);
atomic_store_explicit(flag, st=2, memory_order_release);
}
while (st != 2) { st = atomic_load_explicit(flag, memory_order_acquire); }
}
There's a commented version here: https://github.com/mtklein/best/blob/main/once.c https://github.com/mtklein/best/blob/main/once.c