The standard does not guarantee that std::atomics is the same size as the base type, and that atomic operations are not blocked (although they are likely to be for uint32 , at least). Therefore, I am sure that there is no suitable way to combine them into one 64bit atomic operation. Therefore, you need to decide whether you want to manually combine the two variables into 64-bit (and work only with 64-bit operations) or not.
As an example, the platform may not support 64bit CAS (for x86, which was added with the first Pentium IIRC processor, so it will not be available when compiling compatibility with 486. In this case, it needs to be blocked somehow, so the atomic one may contain 64bit as a variable and lock.
As for the fences: Well, it depends on the memory_order that you specify for your operation. If the memory order indicates that the two operations should be visible in the order in which they are subtracted, the compiler obviously will not be able to optimize the guard, otherwise this could happen. Of course, assuming that you only target x86 with memory_order_seq_cst , it actually emits a barrier due to what I remember, so something less will prevent reordering of the commands executed by the compiler, but will not have an actual penalty).
Of course, depending on your platform, you can get away with considering two std::atomic<int32> as one of the int64 , casting either through union or reinterpret_cast , just keep in mind that this behavior is not required by the standard and can (at least least theoretically) stop working at any time (new compiler check, various optimization settings, ...)
source share