Earlier quoted context omitted.
The use of volatile is typical here. It allows the ring buffer to be used from interrupts, as long as you have one reader and one writer at a time. I haven't checked the code for correctness, but in a typical ring buffer implementation intended to be used in interrupts, you would make the read and write pos volatile. To write, you put the value in the array, and then advance the write position. To read, you copy a va…
> The use of volatile is typical here. This is definitely true. C++ programmers typically do this. > It allows the ring buffer to be used from interrupts Unfortunately "allows" here is telling us about the programmers not the hardware. The programmers see this and figure eh, I don't really understand this but somebody wrote "volatile" so I guess they knew what they were doing. > Volatile ensures that if a read is int…
While the abstract machine is not allowed to reorder volatile writes, the compiler is NOT obliged to emit instructions forcing the actual hardware not to reorder writes. Thus, regular cache behavior can turn your carefully ordered sequence of volatile writes into a bunch of local cache operations followed by a single writeback bus transaction.
If you are coding to a microcontroller, its cache hardware might be simple enough that this can't happen. Or, you might be able (and need!) to initialize a memory controller, at startup, to give a chosen memory address range simpler write semantics, e.g. "write-through".
But atomics are the cleanest way to express things at the source level.