Why does volatile exist?
volatile
is needed if you are reading from a spot in memory that, say, a completely separate process/device/whatever may write to.
I used to work with dual-port ram in a multiprocessor system in straight C. We used a hardware managed 16 bit value as a semaphore to know when the other guy was done. Essentially we did this:
void waitForSemaphore()
{
volatile uint16_t* semPtr = WELL_KNOWN_SEM_ADDR;/*well known address to my semaphore*/
while ((*semPtr) != IS_OK_FOR_ME_TO_PROCEED);
}
Without volatile
, the optimizer sees the loop as useless (The guy never sets the value! He's nuts, get rid of that code!) and my code would proceed without having acquired the semaphore, causing problems later on.
C++ Why does the const volatile type qualifier exist?
If you define
const some_type x = some_value;
that means you can't modify the value of x
. In the absence of volatile
, the compiler can replace a reference to x
by some_value
.
If you define
const volatile some_type x = some_value;
then you still can't modify x
(at least not by using the name x
), but the compiler can no longer assume that its value cannot change. Any reference to the value of x
must actually load its value from memory; it can't assume that it will always retain its initial value.
For example, there might be some compiler-specific attribute that associates x
with some device. The name x
provides a read-only view of the object; the volatile
inhibits certain optimizations.
Why do we use volatile keyword?
Consider this code,
int some_int = 100;
while(some_int == 100)
{
//your code
}
When this program gets compiled, the compiler may optimize this code, if it finds that the program never ever makes any attempt to change the value of some_int
, so it may be tempted to optimize the while
loop by changing it from while(some_int == 100)
to something which is equivalent to while(true)
so that the execution could be fast (since the condition in while
loop appears to be true
always). (if the compiler doesn't optimize it, then it has to fetch the value of some_int
and compare it with 100, in each iteration which obviously is a little bit slow.)
However, sometimes, optimization (of some parts of your program) may be undesirable, because it may be that someone else is changing the value of some_int
from outside the program which compiler is not aware of, since it can't see it; but it's how you've designed it. In that case, compiler's optimization would not produce the desired result!
So, to ensure the desired result, you need to somehow stop the compiler from optimizing the while
loop. That is where the volatile
keyword plays its role. All you need to do is this,
volatile int some_int = 100; //note the 'volatile' qualifier now!
In other words, I would explain this as follows:
volatile
tells the compiler that,
"Hey compiler, I'm volatile and, you
know, I can be changed by some XYZ
that you're not even aware of. That
XYZ could be anything. Maybe some
alien outside this planet called
program. Maybe some lightning, some
form of interrupt, volcanoes, etc can
mutate me. Maybe. You never know who
is going to change me! So O you
ignorant, stop playing an all-knowing
god, and don't dare touch the code
where I'm present. Okay?"
Well, that is how volatile
prevents the compiler from optimizing code. Now search the web to see some sample examples.
Quoting from the C++ Standard ($7.1.5.1/8)
[..] volatile is a hint to the
implementation to avoid aggressive
optimization involving the object
because the value of the object might
be changed by means undetectable by an
implementation.[...]
Related topic:
Does making a struct volatile make all its members volatile?
Understanding volatile keyword in c++
The volatile
keyword in C++ was inherited it from C, where it was intended as a general catch-all to indicate places where a compiler should allow for the possibility that reading or writing an object might have side-effects it doesn't know about. Because the kinds of side-effects that could be induced would vary among different platforms, the Standard leaves the question of what allowances to make up to compiler writers' judgments as to how they should best serve their customers.
Microsoft's compilers for the 8088/8086 and later x86 have for decades been designed to support the practice of using volatile
objects to build a mutex which guards "ordinary" objects. As a simple example: if thread 1 does something like:
ordinaryObject = 23;
volatileFlag = 1;
while(volatileFlag)
doOtherStuffWhileWaiting();
useValue(ordinaryObject);
and thread 2 periodically does something like:
if (volatileFlag)
{
ordinaryObject++;
volatileFlag=0;
}
then the accesses to volatileFlag
would serve as a warning to Microsoft's compilers that they should refrain from making assumptions about how any preceding actions on any objects would interact with later actions. This pattern has been followed with the volatile
qualifiers in other languages like C#.
Unfortunately, neither clang nor gcc includes any option to treat volatile
in such a fashion, opting instead to require that programmers use compiler-specific intrinsics to yield the same semantics that Microsoft could achieve using only the Standard keyword volatile
that was intended to be suitable for such purposes [according to the authors of the Standard, "A volatile
object is also an appropriate model for a variable shared among multiple processes."--see http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf p. 76 ll. 25-26]
Everything is volatile
In C++, volatile
has nothing to do with thread safety. You cannot rely on it to avoid data races. Its purpose is to force synchronised accesses to a variable (from a single thread, or threads that use some other mechanism to synchronise with each other) to happen exactly in the order specified. This is often necessary when interacting with hardware, to prevent accesses that appear to do nothing, but actually affect the state of the hardware, from being optimised away. It gives no guarantees about the effect of unsynchronised accesses.
To avoid data races, you must use either atomic operations or explicit locks to synchronise access to shared objects. C++11 provides these in the standard library; if you're stuck in the past, then you'll have to rely on whatever libraries (such as pthreads) or language extensions (such as atomic intrinsics) are available on your platform.
C++ - What does volatile represent when applied to a method?
It is a volatile member which, just like a const member can only be called on const objects, can only be called on volatile objects.
What's the use? Well, globally volatile is of little use (it is often misunderstood to be applicable for multi-threaded -- MT -- programming, it isn't the case in C++, see for instance http://www.drdobbs.com/high-performance-computing/212701484), and volatile class objects are even less useful.
IIRC A. Alexandrescu has proposed to use the type checking done on volatile objects to statically ensure some properties usefull for MT programming (say that a lock has been taken before calling a member function). Sadly, I don't find the article back. (Here it is: http://www.drdobbs.com/184403766)
Edit: added links from the comments (they where added also in the question).
Related Topics
How to Propagate Exceptions Between Threads
What Are the Pointer-To-Member Operators -≫* and .* in C++
Dividing Two Integers to Produce a Float Result
What Made I = I++ + 1; Legal in C++17
How to Print the Wchar_T Values to Console
C++ Vector Size. Why -1 Is Greater Than Zero
Difference Between (Type)Value and Type(Value)
Efficient String Concatenation in C++
Rand() % 14 Only Generates the Values 6 or 13
How to Get the Md5 Hash of a File in C++
What Makes More Sense - Char* String or Char *String
How to Get Iostream to Perform Better
Public Data Members VS Getters, Setters
Can Standard Container Templates Be Instantiated With Incomplete Types