Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C++11 guarantee memory ordering between a release fence and a consume operation?

Consider the following code:

struct payload
{
    std::atomic< int > value;
};

std::atomic< payload* > pointer( nullptr );

void thread_a()
{
    payload* p = new payload();
    p->value.store( 10, std::memory_order_relaxed );
    std::atomic_thread_fence( std::memory_order_release );
    pointer.store( p, std::memory_order_relaxed );
}

void thread_b()
{
    payload* p = pointer.load( std::memory_order_consume );
    if ( p )
    {
        printf( "%d\n", p->value.load( std::memory_order_relaxed ) );
    }
}

Does C++ make any guarantees about the interaction of the fence in thread a with the consume operation in thread b?

I know that in this example case I can replace the fence + atomic store with a store-release and have it work. But my question is about this particular case using the fence.

Reading the standard text I can find clauses about the interaction of a release fence with an acquire fence, and of a release fence with an acquire operation, but nothing about the interaction of a release fence and a consume operation.

Replacing the consume with an acquire would make the code standards-compliant, I think. But as far as I understand the memory ordering constraints implemented by processors, I should only really require the weaker 'consume' ordering in thread b, as the memory barrier forces all stores in thread a to be visible before the store to the pointer, and reading the payload is dependent on the read from the pointer.

Does the standard agree?

like image 209
Edmund Kapusniak Avatar asked Jun 20 '15 07:06

Edmund Kapusniak


1 Answers

Your code works.

I know that in this example case I can replace the fence + atomic store with a store-release and have it work. But my question is about this particular case using the fence.

Fence with relaxed atomic operation is stronger than corresponded atomic operation. E.g. (from http://en.cppreference.com/w/cpp/atomic/atomic_thread_fence, Notes):

While an atomic store-release operation prevents all preceding writes from moving past the store-release, an atomic_thread_fence with memory_order_release ordering prevents all preceding writes from moving past all subsequent stores.

like image 132
Tsyvarev Avatar answered Nov 15 '22 14:11

Tsyvarev