I'd like to know of an example of a problem which was solved by adding the volatile keyword.
I'm sure it has helped somebody solve something, but I don't know where I would actually apply it.
In my case, it has never been the answer.
I'd like to know of an example of a problem which was solved by adding the volatile keyword.
I'm sure it has helped somebody solve something, but I don't know where I would actually apply it.
In my case, it has never been the answer.
In developing embedded systems or device drivers, where you need to read or write a memory-mapped hardware device. The contents of a particular device register could change at any time, so you need the volatile
keyword to ensure that such accesses aren't optimised away by the compiler.
Yes, 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 hw 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 the semaphore, causing problems not just for my code but for my career...
Here is an interesting discussion about volatile with regards to the Singleton pattern: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
Developing for an embedded, I have a loop that checks on a variable that can be changed in an interrupt handler. Without "volatile", the loop becomes a noop - as far as the compiler can tell, the variable never changes, so it optimizes the check away.
Same thing would apply to a variable that may be changed in a different thread in a more traditional environment, but there we often do synchronization calls, so compiler is not so free with optimization.
From an Embedded Systems Article by Dan Saks:
"A volatile object is one whose value might change spontaneously. That is, when you declare an object to be volatile, you're telling the compiler that the object might change state even though no statements in the program appear to change it."
Links to 2 great articles by Mr. Saks regarding the volatile keyword:
http://www.embedded.com/columns/programmingpointers/174300478 http://www.embedded.com/columns/programmingpointers/175801310
There is an intriguing technique that makes your compiler detect possible race conditions that relies heavily on the volatile keyword, you can read about it at http://www.ddj.com/cpp/184403766.
Most modern processors have floating point registers that have more than 64 bits of precision. That way, if you run several operations on double-precision numbers, you actually get a higher-precision answer than if you were to truncate each intermediate result to 64 bits.
This is usually great, but it means that depending on how the compiler assigned registers and did optimizations, you'll have different results for the exact same operations on the exact same inputs. If you need consistency, then you can force each operation to go back to memory by using the volatile keyword.
It's also useful for some algorithms that make no algebraic sense, but reduce floating point error, such as Kahan summation. Algebraicly it's a nop, so it will often get incorrectly optimized out, unless some intermediate variables are volatile.
Beside the fact that the volatile keyword is used for telling the compiler not to optimize the access to some variable (that can be modified by a thread or an interrupt routine), it can be also used to remove some compiler bugs -- YES it can be ---.
For example I worked on an embedded platform were the compiler was making some wrong assuptions regarding a value of a variable. If the code wasn't optimized the program would run ok. With optimizations (which were really needed because it was a critical routine) the code wouldn't work correctly. The only solution (though not very correct) was to declare the 'faulty' variable as volatile.
A large application that I used to work on in the early 1990s contained C-based exception handling using setjmp and longjmp. The volatile keyword was necessary on variables whose values needed to be preserved in the block of code that served as the "catch" clause, lest those vars be stored in registers and wiped out by the longjmp.
I've used it in debug builds when the compiler insists on optimizing away a variable that I want to be able to see as I step through code.
Besides using it as intended, volatile is used in (template) metaprogramming. It can be used to prevent accidental overloading, as the volatile attribute (like const) takes part in overload resolution.
You MUST use volatile when implementing lock-free data structures. Otherwise the compiler is free to optimize access to the variable, which will change the semantics.
To put it another way, volatile tells the compiler that accesses to this variable must correspond to a physical memory read/write operation.
For example, this is how InterlockedIncrement is declared in the Win32 API:
LONG __cdecl InterlockedIncrement(
__inout LONG volatile *Addend
);