1

I have two questions:

  1. In the general case is it safe to use an atomic as a T and switch between them interchangeably?
  2. In the case of a futex is it safe to do the cast?

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);
Ebony Ayers
  • 350
  • 1
  • 3
  • 9
  • 5
    Looks like blatant UB. – Evg Feb 20 '21 at 14:34
  • The reason why you haven't found an answer for the reverse is pretty simple: most folks just atomically load or store a regular T value into the atomic T as required. operator T and operator = are your friends. The cost of stacking a T is usually small compared to the cost of introducing Unknown Behavior. – Abel Feb 20 '21 at 15:41
  • Re: `(*bar)++` -- presumably the goal here is to do a non-atomic increment. If that's acceptable, then just use a non-atomic object. If you're going to bypass atomicity, being atomic is pointless. – Pete Becker Feb 20 '21 at 16:01
  • No, but I've seen some professional libraries do it to mix C++ atomics and futexes together.. It's still UB – David Haim Feb 20 '21 at 17:23

1 Answers1

3

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.

Jeff Garrett
  • 5,863
  • 1
  • 13
  • 12