-1

I know old C++ know nothing about threads, so this is a Q about IRL compilers, not standard.

I recently was writing a code that has something like this in it:

// runs until sun shines or until shutdown is signaled from another thread  
// const is here just to make it clear run is not touching variable 
void run(const bool& shutdown_in_progress) 
{
while(! shutdown_in_progress) //1
{
    //populate data
    for (int i = 0; i< data.size();++i)
    {
         if (shutdown_in_progress) //2
             break; // shutdown latency optimization
         do_slow_stuff_with(data[i]);
    }

}

Now lets say I add synchronization to access to shutdown_in_progress(so that there is no race condition on that variable).

Am I wrong to think that compilers even with for example pthread_mutex_lock/unlock guarding access to the bool could do destructive optimizations that would replace while(//1) with if and totally remove //2 because it knows variable must be false. Or compilers had a way to detect possible mutation of a variable when it is surrounded with syncronization code?

this is not a theoretical problem, Im working on embeded system with an old g++ compiler. :)

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • Good resource: [http://stackoverflow.com/a/4437555/1807078](http://stackoverflow.com/a/4437555/1807078) – Chris Cooper Feb 07 '14 at 19:24
  • This cannot be answered in its current form. From the language perspective everything goes pre C++11, as it is thread-unaware. But compilers would offer guarantees that the compiler might not offer. If the platform is posix and you have pthreads, chances are the library and the compiler will work together to make it work – David Rodríguez - dribeas Feb 07 '14 at 19:27
  • @ChrisCooper so you are saying that pthread_mutex* + volatile will make it work, but using just one of those 2 will cause pain and sadness – NoSenseEtAl Feb 07 '14 at 19:27
  • @DavidRodríguez-dribeas I think I address that in my Q. It is UB from ISO point of view, what I care about is RL compilers, specifically g++ and pthread combo – NoSenseEtAl Feb 07 '14 at 19:28
  • How old is that g++ compiler? You might investigate upgrading it, compilers of that [era](http://en.wikipedia.org/wiki/GNU_Compiler_Collection#EGCS_Fork) may have been a bit on the buggy side. – Elliott Frisch Feb 07 '14 at 19:29
  • @ElliottFrisch it is not just my decision, it is bigger than me... and it is not just about will, a lot of work would had to be done to maybe successfully upgrade... and age is 5+y :( but still it is 4.smthing – NoSenseEtAl Feb 07 '14 at 19:32
  • @NoSenseEtAl: Yet you don't mention what platform or version of gcc. So you basically ask: I know this depends on parameters X and Y, can you guess X and Y and then answer the question? As mentioned before, the generic answer is that if there is a pthreads implementation, the compiler provides *sufficient* support for that – David Rodríguez - dribeas Feb 07 '14 at 19:36
  • It is difficult to say what the compiler will do without checking the generated assembly. But declaring the parameter as volatile (i.e. volatile const bool& shutdown_in_progress) will stop possible optimizations. – Nipun Talukdar Feb 07 '14 at 19:38
  • @DavidRodríguez-dribeas if that is true make it an A and ill accept – NoSenseEtAl Feb 07 '14 at 19:39
  • @NoSenseEtAl: No, that cannot be an answer without more specifics. There is a difference between a *guess* and an *answer*, and your question is ill-formed and does not allow for *answers*, only for *guesses* – David Rodríguez - dribeas Feb 07 '14 at 19:42
  • compiler version is 4.1.1 idk how to check for pthread version or if that matters – NoSenseEtAl Feb 07 '14 at 19:45

1 Answers1

1

As you say yourself, you are off the limits of the C++ standard here. Practically, there are compilers that assume that shutdown_in_progress does not change, if they can prove nothing inside the while loop is able to change it.

In your case, shutdown_in_progress is a reference to a boolean variable. So the compiler does in general not know whether that variable is accessed using another name somewhere else. For example it might refer to a global variable that might be changed by do_slow_stuff_with. If the source code for that function is in the same file, and there are no assignments to any boolean variables in that function, alias analysis might kick in and tell the compiler there are no write accesses to any boolean variables, so definitely nothing aliases shutdown_in_progress. But as soon as you call some function outside the current translation unit, older versions of gcc can not optimize the access away.

There might be a second way for gcc to prove there is no access to the boolean variable refered to by shutdown in_progress which is by tracing whether there are any other references to the real target created. For example if the target of the reference is a local variable of the caller, and the caller never passed the address of that variable to any other function, gcc can be sure there are no aliases, so that there is no way for that variable to change. In your case, I am quite sure this kind of optimization (if done at all) does not apply, as you surely have passed the address of shutdown_in_progress to another function that could initiate shutdown, or it is a global variable.

Finally, gcc makes sure not to optimize any accesses to variables declared as volatile. While the C++ standard does not guarantee anything about volatile variables in connection with threads, and even in practice you might get very unexpected results if you try to synchronize through volatile variables without using pthread primitives, in this case, using a volatile variable seems to be safe. The problem with volatiles is, that they make sure the write instructions when assigning to multiple of them are ordered correctly, but there is no guarantee readers observe the effects of the writes in that order.

And as a last point, if you don't add pthread function calls and have an evil processor architecture, one processor core executing the function you wrote might work with a stale cached copy of the referenced boolean variable for an indefinite amount of time.

Michael Karcher
  • 3,803
  • 1
  • 14
  • 25