3

Given the below code:

static int x;

static void f() {
  for (int i = 0; i < 100; ++i)
    atomic_fetch_add(&x, 3);
}

Further, assume that f is called by two threads concurrently. Does C/C++ memory model guarantee that the result would always be 600 on all hardware platforms?

And what if I changed it to the below? Is the result still guaranteed to be 600 on all hardware platforms?

static atomic_int a_x;

static void f() {
  for (int i = 0; i < 100; ++i)
    a_x += 3;
}

Or the result is not guaranteed and I should never mix atomic operations with non-atomic types and vice versa?

PS: I used an int type here but my question applies to any type T and _Atomic T.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
cmutex
  • 1,478
  • 11
  • 24
  • 2
    What is specifically unclear from the [`atomic_fetch_add()` reference](https://en.cppreference.com/w/c/atomic/atomic_fetch_add) for you? – πάντα ῥεῖ Feb 05 '21 at 16:11
  • 2
    This is easier to answer if you choose between C and C++ – klutt Feb 05 '21 at 16:15
  • It doesn't say anything about mixing atomic variables with non-atomic operations and vice versa. And gcc compiles both without any warning. – cmutex Feb 05 '21 at 16:15
  • tl;dr: pointers to atomic and non-atomic types are not compatible with each other, so passing `&x` to `atomic_fetch_add` is not valid. – trent Feb 05 '21 at 16:19
  • (The second snippet *is* guaranteed to result in `a_x == 100`. [Built-in increment and decrement operators and compound assignment are read-modify-write atomic operations with total sequentially consistent ordering](https://en.cppreference.com/w/c/language/atomic); i.e. `a_x += 3` *is* an atomic operation.) – trent Feb 05 '21 at 16:21
  • @trentcl: did you mean `a_x=600`? – Ari Feb 05 '21 at 16:41
  • 1
    Yes... yes, I did. – trent Feb 05 '21 at 16:48

1 Answers1

4

If you want to use atomic operations on non-atomic variables, you can use std::atomic_ref (C++20). You can see an example here.

Your second example should be fine because a_x is atomic with memory_order_seq_cst memory model and += is defined for it as an atomic operation.

Ari
  • 7,251
  • 11
  • 40
  • 70
  • Same is true of the += operator in C: https://en.cppreference.com/w/c/language/operator_assignment. Thanks! – cmutex Feb 05 '21 at 16:31
  • 1
    @user3124390: It's at 6.5.16.2 (3) in the C17 standard. Incidentally, there is a (non-normative) note 7.17.7.5(5) which contradicts this and says they are not guaranteed atomic, but this seems to be an error and is mentioned in [Defect Report 486](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2244.htm#dr_486). – Nate Eldredge Feb 05 '21 at 17:02