3

I'm working with C++ 11 and I encountered a class with a volatile member variable, which raised a question:

Question 1:

if a member variable is set in one class function and polled in another class function - is there ever a need for volatile? If so, when? (I know that if x is mapped to hardware register we should use volatile, I mean a "pure software" scenario)

Example:

class MyClass
{
public:
    FuncA { if (x==5) print("hello"); }
    FuncB { x=5;}
private:
    volatile int x = 0;
}

Different threads are accessing MyClass instance, but no 2 threads at the same time, so no need to guard x.

Question 2:

Is there a scenario (some kind of optimization) that after FuncB is called FuncA will not print "hello"?

mvk
  • 41
  • 1
  • 6
  • 3
    For your cases there is std::atomic. – Werner Henze Mar 01 '18 at 10:27
  • You will want a [mcve] to illustrate what you mean by _"no 2 threads at the same time"_ – Passer By Mar 01 '18 at 10:35
  • If the behaviour changed because of some optimization, you are causing undefined behaviour. So what you should really be asking is, is this well-defined – Passer By Mar 01 '18 at 10:37
  • 1
    `volatile` is an extremely misunderstood keyword in C++. I've closed to the start of a "duplicate chain" as they should explain it all to you. Upvoted the question though: it's nicely presented and useful. – Bathsheba Mar 01 '18 at 10:38
  • Have a look at this question that discusses the difference between atomic and volatile: https://stackoverflow.com/questions/8819095/concurrency-atomic-and-volatile-in-c11-memory-model – PaulR Mar 01 '18 at 10:56

2 Answers2

0

if a member variable is set in one class function and polled in another class function - is there ever a need for volatile?

No need for volatile.

Is there a scenario (some kind of optimization) that after FuncB is called FuncA will not print "hello"?

When a CPU does a store to memory that store goes into the store buffer first. While in store buffer, other threads won't see the effect of the store until the store has been committed to cache/memory.

See CPU Cache Flushing Fallacy for more details.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
0

if a member variable is set in one class function and polled in another class function - is there ever a need for volatile?

Which method changes a variable is not important. Only which thread is accessing the method which access the variable is the point here!

Different threads are accessing MyClass,

No! Only the objects will accessed, not the class!

but no 2 threads at the same time,

also this is the wrong assumption! There is still the need that the compiler knows that variables are accessed from different context/thread. If the compiler has no knowledge of access from different threads, it is allowed to do all kind of optimizations and cached szenarios like keeping things in registers or not synchronized cpu caches and much more. Different threads can run on different cpu cores and they can have different caches which are not synchronous to other threads. As this, you must tell the compiler that there is access from different threads. Internally, the compiler generates memory barriers for synchronizing the data access.

For you, you have to use lock functions with std::mutex or use std::atomic vars. Volatile will not help in this scenario at all!

Klaus
  • 24,205
  • 7
  • 58
  • 113