2

I'm having trouble wrapping my head around the correct usage of std::atomic_ref<int> with volatile.

Naively there are three possibilities:

std::atomic_ref<volatile int> ref1;
volatile std::atomic_ref<int> ref2;
volatile std::atomic_ref<volatile int> ref3;

When and do we want to use each one? The use-case I'm interested in is MMIO.

iko
  • 53
  • 1
  • 5
  • What is the problem you are solving? – Maxim Egorushkin Sep 23 '20 at 11:26
  • I have a mmap'd struct, which is used as an IPC fifo. Both reads and writes have order requirements. I'm considering relying on the `std::memory_order` of the atomic accesses to implement the memory barriers. – iko Sep 23 '20 at 11:46
  • If the value is memory-mapped to hardware and *all* writes, even identical ones, are important, then `volatile` is needed, otherwise simply `std::atomic_ref ref2` in combination with a default `memory_order::seq_cst` should be enough to guarantee ordering. – rustyx Sep 23 '20 at 11:57
  • @rustyx what do you mean by identical writes: a write to the same memory location, or a write of the same value to the same memory location? – iko Sep 23 '20 at 12:09
  • @rustyx I'm not sure I completely follow why I wouldn't need `volatile` given that a read from the mmap'd struct will tell me the current fifo capacity. – iko Sep 23 '20 at 12:20
  • Using memory mapped between processes for IPC doesn't need `volatile`, `std::atomic` is sufficient. – Maxim Egorushkin Sep 23 '20 at 12:23
  • @MaximEgorushkin Even if I have to read from the value to check the capacity of the fifo? – iko Sep 23 '20 at 14:04
  • That's what atomics are for. – Maxim Egorushkin Sep 23 '20 at 14:12
  • Is there then a scenario where I would want a `std::atomic`? – iko Sep 23 '20 at 14:16
  • Interesting discussion on volatile and atomics https://github.com/isocpp/CppCoreGuidelines/issues/1231#issuecomment-400704968 – iko Sep 28 '20 at 13:01

1 Answers1

3

Unlike std::atomic<T>, std::atomic_ref<T> does not have volatile-qualified methods. So, you probably can't do much with a volatile std::atomic_ref<T> (whether T is itself volatile or not).

This makes sense given the quote

Like language references, constness is shallow for atomic_ref - it is possible to modify the referenced value through a const atomic_ref object.

Assuming cv-qualification is somewhat consistent, a shallowly-volatile atomic_ref is unlikely to be useful, and definitely isn't what you're asking for.

So, you want

std::atomic_ref<volatile int>

Note that it may be sufficient to just use std::atomic_ref<int>, but since the standard doesn't make any explicit guarantees about MMIO, you should probably consult your compiler documentation and/or check the code it generates.

Depending on std::atomic in this way is at least not portable. Specifically, this answer and its linked paper mention some ways in which std::atomic may be inadequate - you can check whether these are actual problems for you.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • Good point regarding the lack of the volatile methods, I hadn't noticed. I was also leaning towards `std::atomic_ref`. Thanks – iko Sep 23 '20 at 11:53