Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ volatile keyword with global shared variable accessed by function

I have a multi-threaded C++ application.

Now I know that for global shared variables, you should use volatile in some cases while checking the state of the variable or else the compiler could assume that the variable's value never changes (in that thread).

What if, however, instead of checking the status of a variable I call a method that returns the value of the variable? For instance:

static int num = 0;

...

void foo()
{
   while(getNum() == 0)
   {
      // do something (or nothing)
   }
}

Would I still have to make num a volatile variable? or does the compiler recognize that since I'm using a method to access that variable num it won't cache the result?

Anyone got any ideas?

Thanks in advance,

~Julian

edit: inside my while loop I removed the sleep call and replaced it with something generic such as a comment to do something (or nothing)

like image 377
jbu Avatar asked Sep 06 '10 09:09

jbu


1 Answers

No, volatile is never needed as long as you're doing the necessary synchronization.

Calling thread library synchronization functions, whatever they are on your platform, should take care of invalidating locally "cached" values and making the compiler reloads globals.

In this particular case, sleep is likely to have such an effect, but it's not a good implementation anyway. There should be a condition variable on num, protect it with a setter function, and have the setter function send a signal to foo.

As to the specific question, whether the function hides the access from optimization is extremely implementation- and situation-dependent. Your best bet is to compile the getter function in a separate invokation of the compiler, but even then, there's no way to guarantee that interprocedural optimization doesn't occur. For example, some platforms may put IR code in the .o files and perform code generation in the "linker" stage.

Disclaimer.

Key words above: 1. as long as you're doing the necessary synchronization and 2. likely to have such an effect.

1: sleep or an empty busy-loop are not "necessary synchronization." That is not the correct way to write a multithreaded program, period. So, volatile may be needed in such cases.

2: Yes, sleep may not be counted by the implementation an I/O function, and may even be labeled as pure and free of side-effects. In that case, volatile on the global would be necessary. However, I doubt any implementations have really been distributed which would break sleep loops like that, since they are unfortunately common.

like image 136
Potatoswatter Avatar answered Sep 30 '22 01:09

Potatoswatter