4

Like the title says - is there any case in which volatile is useful in the context of singlethreaded programming? I know it's used to make sure the value of the variable is always actually checked in memory so is there any case in which that value may change (in a ST app) in a way that the app/compiler won't notice?

I'm leaving this question language-agnostic as I'm not aware of any differences between them that would affect the answer to this question. But if there are any please let me know.

Edit: As it's been pointed out to me, the question isn't language-agnostic. I'm making it C++ specific then (I've read that there are differences in C++ versions as well but I hope they aren't big enough to make this question too broad).

NPS
  • 6,003
  • 11
  • 53
  • 90
  • 1
    Do note that `volatile` means something else in C/C++ as opposed to Java/C#. `volatile` in Java/C# are actualy `std::atomic` in C++. – David Haim Feb 04 '16 at 10:34
  • I don't think this is a language agnostic question. The meaning of `volatile` is very different in C++ and Java. – Yu Hao Feb 04 '16 at 10:34
  • Yeah, the question makes no sense at all. The `volatile` keyword means one thing in Java, one thing in C, something else in C#, yet a different thing in C++-11, and is subtly different in C++ versions prior to C++-11. I have no idea where to start answering this, voting to close as too broad. – David Schwartz Feb 04 '16 at 10:37

3 Answers3

4

This is an answer for C and C++

Yes! When the variable is mapped to a hardware register (an I/O device for instance). The hardware modifies the register, independently of the application.

Example:

extern volatile uint32_t MY_DEVICE_START; // write-only register
extern volatile const uint32_t MY_DEVICE_STATUS; // read-only register
extern volatile uint32_t MY_DEVICE_DATA; // read-write register

...
MY_DEVICE_DATA = 42; // send input to the device
MY_DEVICE_START = 1; // start the device
while (MY_DEVICE_STATUS == 0) {} // busy-wait for the device to finish
int result = MY_DEVICE_DATA; // read output from the device
...

At least in C/C++ that's the main reason for it. Volatile is even not recommended for multi-threaded use.

Community
  • 1
  • 1
bolov
  • 72,283
  • 15
  • 145
  • 224
3

Other answers have addressed what volatile is, but I want to give a real-world example I use for when volatile can be useful (without trying to read from/write to special hardware memory locations).

One example where volatile can be useful in a C or C++ program is for debugging. Consider the following example:

void do_thing(const std::vector<int>& v) {
    if (v.empty()) {
        do_thing_1();
    } else {
        do_thing_2();
    }
}

If I want to test the above function and force it to take the true or false branch while debugging, I can insert a volatile variable into the if condition:

void do_thing(const std::vector<int>& v) {
    volatile bool condition = v.empty();
    if (condition) {
        do_thing_1();
    } else {
        do_thing_2();
    }
}

I make it volatile so the optimizer doesn't totally optimize away the variable. This makes it simple to set a breakpoint on the if and then I can modify condition (without having to modify v).

I can also make the condition a static variable so I don't have to keep hitting the breakpoint: I can hit it once, set it, and then it will "remember" my choice.

It's a hack, certainly, but I've found it to be very useful in some particular situations.

Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • What would be different if the condition variable weren't volatile? – NPS Feb 04 '16 at 20:05
  • 1
    @NPS: The optimizer can completely optimize away the `condition` variable. This can result in two situations: 1) the optimizer can deduce the result of `v.empty()` at compile time and will force a particular branch to be taken; or 2) the `condition` variable is optimized away and the only way to force one of the branches to be taken (in the debugger) is to modify `v` itself. If it's `volatile`, though, the optimizer can't optimize it too heavily, so the debugger can still modify the control flow. – Cornstalks Feb 05 '16 at 02:02
1

A single threaded program can also have signal handling or even on non-multithreaded platforms hardware interrupt handling can be used, so non-local variables modified in the handler function should be declared as volatile.

p.s. the answer is more or less generic and may be incorrect depending on language as already is mentioned above.

n0p
  • 713
  • 10
  • 23
  • No. `volatile` is the wrong tool - it is underspecified and in any case don't give you the guarantees that you want. With C++11 we (finally) got a well defined memory model and an acknowledgement that threads exist. The standard contains the tools you need (which is *not* `volatile`) like http://en.cppreference.com/w/cpp/atomic/memory_order - sure, you can use `volatile` to suppress compiler optimizations, but that's something else entirely. – Jesper Juhl Feb 18 '17 at 14:56
  • It is not something else, it is the whole point of this answer. The need for "volatile" has been there long before multithreading and C++ (especially C++11) and was mostly used for interrupt handling (lets say signals are also interrupts in this context). The question was initially asked about the concept of "volatile" like as we know it in C in contrast to what it is in Java. Taking into account the existence of "memory_order", I still think that this answer is useful and the use of 'volatile' is more practical and correct in cases described in the answer. – n0p Feb 18 '17 at 16:02