Is there any acausal behavior with dependency loops in the C ++ Depleted Memory Model?

Suppose x

u y

are atomic integers, initialized to 0.

Now Thread A runs the following code:

if (x.load(memory_order_relaxed) == 1) {
    y.store(1, memory_order_relaxed);
}

      

and Thread B runs this code:

if (y.load(memory_order_relaxed) == 1) {
    x.store(1, memory_order_relaxed);
}

      

Is it possible in C ++ to achieve a situation where (x == 1 and y == 1)

? If possible, why?

I saw this claim at https://people.mpi-sws.org/~viktor/slides/2014-07-ec2.pdf (the dependency loop section).

+3


source to share


2 answers


Good question!

These are known as "out of thin air" values, since there is no source for a value of 1. They were omitted in C ++ 11, noted by the N3710 paper , and prohibited in C ++ 14.



As noted by N3710,

No known implementations actually give such results.

+4


source


Often with these questions it is possible to answer the question without understanding what atomic variables are, imagine all the possible scenarios.

What is an atomic operation? This is an operation that cannot be broken. This is either done or not done.

With this in mind, let's consider all possible scenarios.

  • Can any of these cases go into an if condition? Not. Since both are variables 0

    and nothing will turn them into 1

    .

It sounds trivial, but all your possibilities. The more important question is, why should x or y become 1

in the first place? Based on what you provided. There is no reason.




EDIT:

My only comment on this presentation that you linked is that this is simply wrong. To prove it, I used this program and the cases never went into if conditions. Anyone reading this please confirm what I am saying because I may be wrong. I ran this program for a few minutes and nothing happened (gcc (Debian 6.2.1-5) 6.2.1 20161124)

.

#include <iostream>
#include <atomic>
#include <thread>

std::atomic_int x,y;

void call1()
{
    while(true)
    {
        if(x.load(std::memory_order_relaxed) == 1)
        {
            std::cout<<"I'm in!"<<std::endl;
            y.store(1, std::memory_order_relaxed);
        }
    }
}

void call2()
{
    while(true)
    {
        if(y.load(std::memory_order_relaxed) == 1)
        {
            std::cout<<"I'm also in!"<<std::endl;
            x.store(1, std::memory_order_relaxed);
        }
    }
}

int main()
{
    x.store(0);
    y.store(0);

    std::thread t1(call1);
    std::thread t2(call2);

    t1.join();
    t2.join();

    return 0;
}

      

+1


source







All Articles