I have two questions:
I am aware that performing atomic operations on non-atomic types is undefined behaviour but I cannot find an answer for the reverse. For example, this which compiles and executes as expected:
std::atomic_int foo = 5;
int* bar = reinterpret_cast<int*>(&foo);
(*bar)++;
std::cout << (*bar) << std::endl;
As to the second question, the Linux manpage says in the FUTEX_WAIT operation
The load of the value of the futex word is an atomic memory access (i.e., using atomic machine instructions of the respective architecture). This load, the comparison with the expected value, and starting to sleep are performed atomically and totally ordered with respect to other futex operations on the same futex word.
So is the following code safe?
std::atomic_int32_t val = 0;
syscall(SYS_futex, reinterpret_cast<int*>(&val), FUTEX_WAIT_PRIVATE, 0, nullptr);
In the general case is it safe to use an atomic as a T and switch between them interchangeably?
Not with reinterpret_cast
. reinterpret_cast
is only safe in the cases where it is explicitly listed as such, and this is not one.
You can however turn a T
temporarily into an atomic object with std::atomic_ref
.
In the case of a futex is it safe to do the cast?
No.
However, std::atomic_ref
has a similar API to std::atomic
, including wait
.