Поддерживает ли С++ 11 порядок памяти между заборным ограждением и потреблением?
Рассмотрим следующий код:
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 ) );
}
}
Предоставляет ли С++ какие-либо гарантии относительно взаимодействия забора в потоке a с потребностью в потоке b?
Я знаю, что в этом примере я могу заменить забор + атомный магазин с хранилищем-хранилищем и заставить его работать. Но мой вопрос касается этого конкретного случая с использованием забора.
Чтение стандартного текста Я могу найти положения о взаимодействии заборного ограждения с заборным ограждением и заборного ограждения с операцией получения, но ничего о взаимодействии заборного ограждения и операции потребления.
Замена потребления на приобретение приобрела бы код, соответствующий стандарту. Но насколько я понимаю ограничения порядка памяти, реализованные процессорами, я должен действительно требовать более слабое "потребление" в потоке b, поскольку барьер памяти заставляет все хранилища в потоке a быть видимыми перед хранилищем указателю и чтение полезной нагрузки зависит от чтения с указателя.
Согласен ли стандарт?
Ответы
Ответ 1
Ваш код работает.
Я знаю, что в этом примере я могу заменить забор + атомный магазин с хранилищем-хранилищем и заставить его работать. Но мой вопрос касается этого конкретного случая с использованием забора.
Забор с расслабленной атомной операцией сильнее, чем соответствует атомная операция. Например. (из http://en.cppreference.com/w/cpp/atomic/atomic_thread_fence, Примечания):
В то время как операция хранения с использованием атома предотвращает перемещение всех предшествующих записей из хранилища-хранилища, упорядочение atom_thread_fence с памятью_order_release предотвращает перемещение всех предыдущих записей из всех последующих хранилищ.
Ответ 2
Несмотря на то, что это ясно намерение, способ взаимодействия заборов и атомарных операций означает, что только перечисленные комбинации официально поддерживаются. (Этот стиль спецификации не только многословен, труден для чтения, еще труднее превратить в действительную интуицию, его легко сделать неполным.)
Я ничего не вижу в стандарте, поддерживающем сопряжение операции потребления с барьером освобождения, даже если нормальная реализация не может не поддерживать, кроме как специальными усилиями во время глобальной оптимизации программы, чтобы обнаружить этот конкретный вариант использования и преднамеренно сломать его.