I want to do this:
union {
std::atomic<uint128_t> u128;
struct {
std::atomic<uint64_t> u64_1;
std::atomic<uint64_t> u64_2;
};
};
Several threads will read and write both parts of the union.
Is it safe?
Edit: I use Linux, x86_64, clang 3.3
Edit2: I want to be able to increment and decrement u64_1, read u64_2, and write u128 (compare_exchange)
Edit3: What if I use atomic builtin functions? The union will look like this:
union {
uint128_t u128;
struct {
uint64_t u64_1;
uint64_t u64_2;
};
};
u64_1 will map to first half of u128 and u64_2 will map to second half.
The std::atomic<T>
operations can be either lockless or locking, depending on whether the architecture offers the underlying guarantees. You can check this by checking std::atomic<T>::is_lock_free()
.
If the type is not lock free, it might be supported by the library by means of a counter. That in turn probably means that the type is no longer a POD underneath, which in turn means that it is your responsibility to call the constructors/destructors when switching from one active member of the union to another.
If there is a mutex for the 128 bit but not the 64bit types you might end up with a situation in which the layout of the values coincides, but the atomicity of operations is guaranteed by different means, so it might seem to work, but fail spuriously and in a way that is hard to even detect.