Update: First of all, please kindly note that this question does neither involve threading, nor is it about re-ordering or fence-related. Therefore, this does not answer my question (although it's a similar question with an accepted answer): Why is volatile deprecated in C++20?
I guess that there is something important worth clarifying: If you want your code thread-safe, then in many cases, it's not sufficient, to ONLY use volatile. Additional or alternative techniques are required (atomic, lock, etc.). Anyway this question is not about thread-safety.
I recently started my first huge embedded C++ project (with some parts still in C), after many years of pure C with some (inline-)assembler. So far it looks like a good choice: no major performance problems, but tons of optional nice techniques not availabe in C.
Today i wanted to use bind_front
, so i needed to switch to C++20, and was surprised by a huge bunch of "volatile"-related warnings, which is especially unpleasent, as i prefer warning-free code (with all warnings switched on in the compiler).
Apparently some things i sometimes do, are "wrong" in the new standard:
Example1:
for (volatile int i=0; i<10; i++); // very short delay (no alternative way available)
Example2:
...
port->ctrl |= 0x3; // setting some bits in some volatile HW register
In both examples, the volatile
keyword is merely used to keep the compiler from optimizing-away the code.
Here is some background, but not really an explanation for the "why": https://blog.feabhas.com/2021/05/modern-embedded-c-deprecation-of-volatile/
And this still contains no satisfactory explanation: https://www.youtube.com/watch?v=KJW_DLaVXIY (C++ committee language evolution chair )
I agree with the common perception, that some implications of volatile
might be difficult to understand, expecially to beginners or programmers that are "far away" form the hardware.
We know that in a system in which two or more masters can do write access to port->ctrl
at random time, the read-modify-write access wouldn't be safe just by using volatile
. But in some other system, port->ctrl
might be a common read/write hardware register, for which the read-modify-write access actually is safe.
Up to now, port->ctrl |= 0x3
seemed semantically exactly the same as port->ctrl = port->ctrl | 0x3;
But now, only the latter compiles without warning.
Worst thing for me: Sooner or later, i'll have to change tons of perfectly stable and good readable code. But i fail to recognize any improvement.
Actually, the opposite is true: not able to use the shortcut op=
, many of the code lines become much longer, and also redundant, and overall more error-prune.
What do i miss? Can someone enlighten me?