Friday 29 July 2016

Rebellious Volatile

Read this. Seriously, go and read it, I’ll wait right here for you.
Done? Great, now let’s move on with this post.
If you were obedient then you’d know that in the post referred above, I bestowed some heavy praise on the usage of the keyword register. I placed some serious weight on the importance and effectiveness of using it. What if I were to tell you that this whole thing was a setup? That I had this post planned up at the time of writing that one, would you believe me then? Probably not, but here I am, in a somewhat myth busting capacity, hoping to debunk an inception of thought that I may have put in your head before.
Firstly I would like to tell you that using the register keyword is often unnecessary and sometimes even counterproductive. Compilers are smart and enough to recognize which variables are referenced heavily inside of our program. Compilers are benevolent. and enough to do optimizations (the kind of which are achieved by the register keyword) for us, automatically.
The problem with using register is the fact that a variable in a CPU register is in a place too important to be treated as a normal memory address. Simply put, we are not allowed to play around with the address of such a register. The compiler will simply slap an error if we tried any of the pointer concepts on a register variable. This issue is so severe that it has rendered the entire legacy of the register keyword, obsolete and its future, gloomy.
Let me establish one thing, compilers are capable (and eager) to optimize our program for us in ways that go beyond limiting the distance between the variables and the processor. The compiler optimization is a big topic and deserves a dedicated post but the primary purpose of this post is introducing the usage of the keyword volatile. Don’t feel cheated, the above text is there for a reason. Volatile is related to compiler optimization in a very direct way. But before I go into that, let me first describe what volatile is and what its job is:
Volatile is a data type modifier (like register). This means that it is used when a variable is defined, like so:

volatile int x;

What this tells the compiler is that the associated variable can receive a new value from any source at any time. Assignments like x = 5, are not the only way in which this variable will be overwritten. A borrowed definition is:
The volatile modifier tells the compiler that a variable's value may be changed in ways not explicitly specified by the program. This means that a variable can have a change in value without an assignment statement.
This instructs the compiler to explicitly fetch the latest value of the variable every time it is to be used preventing the compiler from performing any trick for the purposes of optimizing the whole fetching the variable from memory saga. So, when you want to prevent a particular variable from the compiler’s optimizations, then using the volatile keyword with the variable definition would be the preferred way to do it. Let’s look at an example scenario, shall we?

int time;
int CurrentTime; 
time = CurrentTime;
/*some amount of time would have passed between these statements, no matter how tiny that amount be./*
While(CurrentTime – time == TARGET)
{
                //Do Something.
}

In this example, the variable time is assigned the value of CurrentTime which is another variable which you can assume returns the current system time at the time of invoking of this variable. In the next statement, we see a while loop which checks to see if the difference between current system time and the variable time is equal to some target. Now, if the compiler is allowed to optimize the whole code, it’ll come to the conclusion that since CurrentTime was assigned to time just immediately before this check statement, the two variables must contain the same value (considering that there are no statements in between that effect the value of either of these two variables). This would then lead the compiler to ignorantly evaluate the left hand side of the check condition to zero. Undesired and inaccurate, the compiler’s optimization can’t be allowed in this particular case.

How can we stop compiler from finding shortcuts in variables accesses? By forcing it to follow the right way of accessing the variable, every time it is to be accessed. And this, my dear reader is done using the volatile keyword. In above example, the variable CurrentTime is to  be made volatile, and the whole program will fall into place.

No comments:

Post a Comment