C++ Volatile Member Functions

C++ volatile member functions

Marking a member function volatile is like marking it const; it means that the receiver object is treated as though it were declared as a volatile T*. Consequentially, any reference to x or y will be treated as a volatile read in the member function. Moreover, a volatile object can only call volatile member functions.

That said, you may want to mark x and y volatile anyway if you really do want all accesses to them to be treated as volatile.

What does it mean when a member function is volatile?

The volatile qualifier on a member function is analogous to the const qualifier. It allows the member function to be called on volatile objects:

struct A {
void f() volatile {}
void g() {}
};

int main() {
A volatile a;
a.f(); // Allowed
a.g(); // Doesn't compile
}

Calling volatile member function using not volatile object in C++

The rule is same as const member function. A volatile member function could be called on a non-volatile object, but a non-volatile member function couldn't be called on a volatile object.

For your case, A::func() will be invoked fine. If you make them opposite, the compilation would fail.

class A 
{
private:
int x;
public:
void func(int a) // non-volatile member function
{
x = a;
cout<<x<<endl;
}
};

int main()
{
volatile A a1; // volatile object
a1.func(10); // fail
return 0;
}

Volatile function

In your code, the volatile keyword does not apply to the function, but to the return type, it is the equivalent of:

typedef volatile int Type;
Type foo();

Now, in C++ you can make a member function volatile, in the same way that the const qualifier, and the behavior is the same:

struct test {
void vfunction() volatile;
};

Basically you cannot call a non-volatile (alterantively non-const) function on a volatile (const respectively) instance of the type:

struct test {
void vfunction() volatile;
void function();
};
volatile test t;
t.vfunction(); // ok
t.function(); // error

Member functions that are volatile and const

If this is marked volatile, it will affect the compiler's ability to optimise away updates to/from the members pointed to by *this.

The TYPICAL use-case for volatile is where you have hardware registers - not particularly typical to use a class to describe hardware registers, but we can do it.

For example, one could have a class like this:

class my_hardware_device
{
public:
int32_t reg1;
int32_t reg2;
private:
int32_t reserved;
public:
int32_t reg4;
int func() volatile;
};

volatile my_hardware_device hw1 =
reinterpret_cast<volatile my_hardware_device*>(0x10000000);
...
int my_hardware_device::func() volatile
{
reg2 = 3;
reg3 = 8;
reg2 = 7;
if (reg2 == 4)
{
...
}
}

...
hw1->func();

Without volatile, the compiler could very well decide to remove the reg2 = 3 and determine that reg2 == 4 is always false, both because of reg2 = 7;. But since it's actually pointing at some hardware, it doesn't behave the way the compiler would expect. [This is a very silly example just constructed to show how it could work - I'm not by any means suggesting that this is a "correct" or "good" solution for any such hardware interface - never mind portability problems, and all manner of other things - and of course the vtable would cause complete havoc if you ever tried to use this with virtual functions - and if you are dealing with hardware in a driver, you probably do want vtables to solve hardware variants, giving yet another reason for implementing this sort of code in a different way.]

The const variant means that the compiler is not allowed to write to members of *this (in other words members in the class foo in your example), except if they are marked as mutable (or if a const_cast is used to cast away the constness - const_cast can also be used to cast away volatileness, by the way).

Combining the both const and volatile simply means that reads can not be optimised away, and the compiler is not allowed to update the members of *this.

c++: volatile member function in volatile instance - assigning array to pointer is invalid conversion?

Volatility and constness do not propagate through pointers, but they do propagate through arrays. So in a volatile instance of the class, firstElementPt is itself volatile, but the thing it points to is not. The intArray elements however are volatile. You are attempting to point a volatile-pointer-to-a-non-volatile-int to a volatile int. This is not allowed.

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).

Volatile Member Functions (C++)

Does the value() member function also have to be marked as volatile to avoid getting optimized away or is it okay as written?

Marking the member function volatile will have no effect on whether it is optimized away or not. It is fine as written.

The worry is if I have MyClass c; and then call c.value(); a couple times, the compiler might think c.value() will return the same value (even though it could have possibly changed..)

It sounds like what you want is to learn about atomic variables. Take a look at std::atomic.

If you really want to learn about volatile, read this paper: http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf



Related Topics



Leave a reply



Submit