c++pointersconstantscompiler-optimization

c++: Is object pointed to by a "pointer to const" considered unchanging or just unmodifiable?


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.


Solution

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