2

In the following situation a "pointer to const bool" parameter pbAbort makes sense because the worker function does not modify the bool object. However, I'm worried the compiler might optimize away multiple checks on the value of the bool unless I use a normal "pointer to bool." The bool is a flag that can be set by the manager thread.

void runWorkManager(DataSet& data)
{
    bool bAbort = false;
    callWorkerFuncFromNewThread(data, &bAbort);
    while(!(data.isWorkCompleted || data.isWorkAborted))
    {
        updateGuiWithProgress(data.progress);
        if(userWantsToAbort())
            bAbort = true;
    }
}
void workerFunc(DataSet& data, bool const *const pbAbort)
{
    data.doPreWork();
    if(*pbAbort) //Check #1
    {
        data.isWorkAborted = true;
        return;
    }

    for(int i = 0; i < 100; ++i)
    {
        data.doWorkN(i);
        if(*pbAbort) //Check #2
        {
            data.isWorkAborted = true;
            return;
        }
    }
    data.isWorkCompleted = true;
}

If *pbAbort is assumed to never change, then the compiler could remove the Check #2 block.

The c++ 11 standard at 7.1.6.1.3 states:

A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path.

Unfortunately, this statement doesn't quite answer my question.

tsandy
  • 911
  • 4
  • 10
  • What is `bool const *const pbAbort` supposed to mean? – tadman Nov 28 '14 at 20:51
  • Why do you need a pointer to a `bool` instead of just a plain ol' `bool`? If the pointer and `bool` are both `const` it can't be that you need to modify an original value somewhere. – caps Nov 28 '14 at 20:52
  • 1
    You could avoid a lot of this mess by using a simple reference that *could* be modified. – tadman Nov 28 '14 at 20:53
  • 1
    @caps: Actually, it *can* be. For example, the other parameter (`data`) might be an object that has a bool member that is modified somewhere in this function. And `pbAbort` might be a pointer to that member. – Benjamin Lindley Nov 28 '14 at 21:05
  • @BenjaminLindley good point. I also noticed from his functions that he could be dealing with threading, in which case another thread might change the value. – caps Nov 28 '14 at 21:19

2 Answers2

2

To answer your question, if the compiler doesn't believe the variable is being modified, it can optimize away multiple reads whether or not the object is const. This is fairly likely to happen in your code considering the code path in the reading thread does not write to the variable.

It is important to note here that your program actually contains undefined behavior; reading an writing variables across threads is not atomic by default. To safely do this, you need an atomic<bool>. See also this question. Also, don't use volatile. It will fix your reordering problem, but access to volatile variables are still not atomic (and so still UB).

The reason the standards statement doesn't answer your question is that it's talking about reads and writes within one thread.

Community
  • 1
  • 1
Dan
  • 12,409
  • 3
  • 50
  • 87
1

If the compiler can't prove the object pointed to is actually const, nothing in the standard allows it to assume that it is - so it can't optimise away the reads.

(If it could see more of the code - e.g. if the functions are inline or whole program optimisation is in use - then it might be able to skip a read when it can tell there have been no writes.)

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64