Monday, April 29, 2019

c++ - 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?

No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...