If I have a C++ method declaration as follows:
class A { public: double getPrice() volatile; };
volatile
represent here?You might be interested in this Dr Dobbs article by Andrei Alexandrescu. I was :)
Edit: That article was written a while back and now it seems that the community has moved on. Herb Sutter has this to say this. Thanks Iain (and Herb!)
mlimber
points out that Andrei had a follow up article here where he continues to advocate the use of volatile correctness as a valuable tool for detecting race conditions on systems supporting POSIX-like mutexes.
Volite is an innovative injectable treatment designed to improve skin quality for up to 9 months. This is not a dermal filler, it's a skin conditioning Hyaluronic acid (HA) gel. Volite is injected into the middle layers of the dermis across many sites to nourish it from the inside out.
A volatile variable is a variable that is marked or cast with the keyword "volatile" so that it is established that the variable can be changed by some outside factor, such as the operating system or other software.
For Java, “volatile” tells the compiler that the value of a variable must never be cached as its value may change outside of the scope of the program itself.
C's volatile keyword is a qualifier that can be used to declare a variable in such a way that the compiler will never optimize away any of the reads and writes.
You're probably familiar with const
methods and const-correctness (cf. "Item 15 - Use const proactively" in C++ Coding Standards by Sutter and Alexandrescu), and volatile
works in similar but slightly different ways to yield what might be called "volatile-correctness."
Like const
, volatile
is a type modifier. When attached to a member function as in your example, either modifier (or both!) mean that the object on which the method is called must have or be convertible to that type.
Consider:
struct A { void f(); void cf() const; void vf() volatile; void cvf() const volatile; // ... }; void foo( A& a, const A& ca, volatile A& va, const volatile A& cva ) { a.f(); // Ok a.cf(); // Ok: Can convert non-const obj to const obj a.vf(); // Ok: Can convert non-volatile obj to volatile obj a.cvf(); // Ok: Can convert non-cv obj to cv obj ca.f(); // Error: can't call non-const method on const obj ca.cf(); // Ok ca.vf(); // Error: can't call non-const method on const obj ca.cvf(); // Ok: Can convert va.f(); // Error: can't call non-volatile method on volatile obj va.cf(); // Error: can't call non-volatile method on volatile obj va.vf(); // Ok va.cvf(); // Ok: Can convert cva.f(); // Error: can't call non-cv method on cv obj cva.cf(); // Error: can't call non-cv method on cv obj cva.vf(); // Error: can't call non-cv method on cv obj cva.cvf(); // Ok }
Note these are compile-time errors, not run-time errors, and that is where it's potential usefulness comes in.
Const-correctness prevents unintentional errors at compile-time as well as making code "easier to understand, track, and reason about" (Sutter and Alexandrescu). Volatile-correctness can function similarly but is much less used (note that const_cast
in C++ can cast away const
, volatile
, or const volatile
, but rather than calling it cv_cast
or similar, it's named after const
alone because it is far more commonly used for casting away just const
).
For instance, in "volatile - Multithreaded Programmer's Best Friend", Andrei Alexandrescu gives some examples of how this can be used to have the compiler automatically detect race conditions in multithreaded code. It has plenty of explanation about how type modifiers work, too, but see also his follow-up comments in his subsequent column.
Update:
Note that C++11 changes the meaning of const
. Thus sayeth the Sutter: "const
now really does mean 'read-only, or safe to read concurrently'—either truly physically/bitwise const
, or internally synchronized so that any actual writes are synchronized with any possible concurrent const
accesses so the callers can’t tell the difference."
Elsewhere, he notes that while C++11 has added concurrency primitives, volatile
is still not one of them: "C++ volatile variables (which have no analog in languages like C# and Java) are always beyond the scope of this and any other article about the memory model and synchronization. That’s because C++ volatile variables aren’t about threads or communication at all and don’t interact with those things. Rather, a C++ volatile variable should be viewed as portal into a different universe beyond the language — a memory location that by definition does not obey the language’s memory model because that memory location is accessed by hardware (e.g., written to by a daughter card), have more than one address, or is otherwise 'strange' and beyond the language. So C++ volatile variables are universally an exception to every guideline about synchronization because are always inherently “racy” and unsynchronizable using the normal tools (mutexes, atomics, etc.) and more generally exist outside all normal of the language and compiler including that they generally cannot be optimized by the compiler.... For more discussion, see my article 'volatile vs. volatile.'"
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With