Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do C++ conditional statements carry a dependency from the condition expression to the statement?

I'm asking specifically in the memory-model sense. http://en.cppreference.com/w/cpp/atomic/memory_order

I'm asking because I want to know if I can use a std::memory_order_consume in the below:

mLocalMemPtr1 and 2 and mAtomicMemPtr are pointers into a shared buffer.

In a producer thread I'm doing:

for (int x = 0; x < 10; ++x)
{
    ++mLocalMemPtr1
    *mLocalMemPtr1 = x;       // <========= A
    mAtomicMemPtr.store(mLocalMemPtr1, std::memory_order_release);
}

And in the consumer:

tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
while (tempMemPtr != mLocalMemPtr2)
{
    ++mLocalMemPtr2;
    int test = *mLocalMemPtr2;   // <======== B
    doSomeLongRunningThing(test);
    tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
}

So does the dependency chain go tempMemPtr -> mLocalMemPtr2 -> test -> doSomeLongRunningThing?

I'm specifically worried that B may be executed before A. I know I can use a std::memory_order_acquire, but I can use consume (which is more lightweight) if the conditional statement causes a memory order dependency.

like image 974
Twisted Oracle Avatar asked May 06 '13 03:05

Twisted Oracle


People also ask

What does the conditional statement Control in C?

C has the following conditional statements: Use if to specify a block of code to be executed, if a specified condition is true. Use else to specify a block of code to be executed, if the same condition is false. Use else if to specify a new condition to test, if the first condition is false.

What expression is in a conditional statement?

The syntax of a conditional expression consists of a conditional statement in parentheses. This can be just like the conditionals used in an if-else statement. This is followed by a question mark, a value to be set if the condition is true, a colon, and finally a value to be set if the condition is false.

What are conditional statements and how many conditions are there name them?

Such statements are called conditional, and are a form of composite statement. In Java, there are two forms of conditional statements: • the if-else statement, to choose between two alternatives; • the switch statement, to choose between multiple alternatives.

Which type of value is returned by a conditional statement?

Conditional states work on measures and aggregations only and return numeric values.


1 Answers

CppReference:

Release-Consume ordering

If an atomic store in thread A is tagged std::memory_order_release and an atomic load in thread B from the same variable is tagged std::memory_order_consume, all memory writes (non-atomic and relaxed atomic) that are dependency-ordered-before the atomic store from the point of view of thread A, become visible side-effects in thread B, that is, once the atomic load is completed, thread B is guaranteed to see everything that thread A wrote to memory if it carries a data dependency into the atomic load.

1.10.10:

An evaluation A is dependency-ordered before an evaluation B if

— A performs a release operation on an atomic object M, and, in another thread, B performs a consume operation on M and reads a value written by any side effect in the release sequence headed by A (...)

1.10.9:

An evaluation A carries a dependency to an evaluation B if - the value of A is used as an operand of B, unless:

— B is an invocation of any specialization of std::kill_dependency (29.3), or

— A is the left operand of a built-in logical AND (&&, see 5.14) or logical OR (||, see 5.15) operator, or

— A is the left operand of a conditional (?:, see 5.16) operator, or

— A is the left operand of the built-in comma (,) operator (5.18); (...)

Basing on these facts I say that mLocalMemPtr2 should be synchronized. However there is still a question of the order of evaluation.

if (atomic.load(std::consume) < x)

Which one is evaluated first is unspecified. There is no guarantee (as I couldn't find it in the standard) that the compiler will first perform consume operation, refresh shared buffer and then load atomic and then x.

Having not found a proof that operands are evaluated in the "wished" way, I say that without explicit decomposition of the atomic load mLocalMemPtr2 it won't work and CPU might read stale value of memory pointed by mLocalMemPtr2. memory_order_acquire would not change much here, as mLocalMemPtr2 carries a data dependency.

like image 116
Red XIII Avatar answered Nov 15 '22 06:11

Red XIII