Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a function to load a non-atomic value atomically?

In C++20 we can write:

double x;

double x_value = std::atomic_ref(x).load();

Is there a function with the same effect?

I have tried std::atomic_load but there seem to be no overloads for non-atomic objects.

like image 653
Pilar Latiesa Avatar asked Jul 01 '20 05:07

Pilar Latiesa


1 Answers

Non-portably of course, there is GNU C __atomic_load_n(&x, __ATOMIC_SEQ_CST) __atomic builtin.

I'm pretty sure you don't find a function in ISO C++ that takes a double * or double &.

Possibly one that takes a std::atomic_ref<double> * or reference, I didn't check, but I think the intent of atomic_ref is to be constructed on the fly for free inside a function that needs it.

If you want such a function, write you own that constructs + uses an atomic_ref. It will all inline down to an __atomic_load_n on compilers where atomic uses that under the hood anyway.


But do make sure to declare your global like this, to make sure it's safe + efficient to use with atomic_ref. It's UB (I think) to take an atomic_ref to an object that's not sufficiently aligned, so the atomic_ref constructor can simply assume that the object you use is aligned the same as atomic<T> needs to be.

alignas (std::atomic_ref<double>::required_alignment)  double x;

In practice that's only going to be a problem for 8-byte primitive types like double inside structs on 32-bit targets, but something like struct { char c[8]; } could in practice be not naturally aligned if you don't ask for alignment.

like image 71
Peter Cordes Avatar answered Oct 23 '22 23:10

Peter Cordes