Search code examples
c++multithreadingc++11instruction-reorderingas-if

Does as-if rule allow this kind of execution reordering


As we know, the compiler or the CPU may reorder the execution as they want, only if they follow the as-if rule. For example, if we have such a piece of code:

C = A + B;
D = E + F;

The compiler or the CPU may execute D = E + F before C = A + B. I can understand that.

Now let's talk about another case.

Saying that I have two threads a and b. I want to set some marks while executing so that I can monitor the whole process of a and b.

queue q; // thread safe

void thread_a()
{
    // do something
    q.push("a - 1");
    // do something
    q.push("a - 2");
}

void thread_b()
{
    // do something
    q.push("b - 1");
    // do something
    q.push("b - 2");
}

My question is: since we have the as-if rule and the execution order may be reordered, does it mean that the messages in the q is not reliable? Meaning that the real execution order is a - 1, b - 1, b - 2 and a - 2 but in the q there might be a - 1, a - 2, b - 1 and b - 2? If this could happen, how should I design or which kind of techinque should I use to monitor the process of multi-threading?


Solution

  • Reordering and multithreading are 2 different things:

    Via multi threading, possible outputs are:

    • "a - 1", "a - 2", "b - 1", "b - 2"
    • "a - 1", "b - 1", "a - 2", "b - 2"
    • "a - 1", "b - 1", "b - 2", "a - 2"
    • "b - 1", "b - 2", "a - 1", "a - 2"
    • "b - 1", "a - 1", "b - 2", "a - 2"
    • "b - 1", "a - 1", "a - 2", "b - 2"

    You just have the guaranty that "a - 1" comes before "a - 2", and "b - 1" comes before "b - 2". (unrelated to reordering)

    Reordering with the as-if rule is just an optimization.

    as_if states:

    The C++ compiler is permitted to perform any changes to the program as long as the following remains true:

    1. Accesses (reads and writes) to volatile objects occur strictly according to the semantics of the expressions in which they occur. In particular, they are not reordered with respect to other volatile accesses on the same thread. (since C++11)
    2. At program termination, data written to files is exactly as if the program was executed as written.
    3. Prompting text which is sent to interactive devices will be shown before the program waits for input.
    4. If the ISO C pragma #pragma STDC FENV_ACCESS is supported and is set to ON, the changes to the floating-point environment (floating-point exceptions and rounding modes) are guaranteed to be observed by the floating-point arithmetic operators and function calls as if executed as written, except that the result of any floating-point expression other than cast and assignment may have range and precision of a floating-point type different from the type of the expression (see FLT_EVAL_METHOD) notwithstanding the above, intermediate results of any floating-point expression may be calculated as if to infinite range and precision (unless #pragma STDC FP_CONTRACT is OFF)

    Your code (except potentially the // do something) does nothing of that, so it can even drop the 2 code completely, push "c - 1".

    But if after you print queue content, then the content should be one of the 6 shown above.