Поддерживает ли С++ 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

Несмотря на то, что это ясно намерение, способ взаимодействия заборов и атомарных операций означает, что только перечисленные комбинации официально поддерживаются. (Этот стиль спецификации не только многословен, труден для чтения, еще труднее превратить в действительную интуицию, его легко сделать неполным.)

Я ничего не вижу в стандарте, поддерживающем сопряжение операции потребления с барьером освобождения, даже если нормальная реализация не может не поддерживать, кроме как специальными усилиями во время глобальной оптимизации программы, чтобы обнаружить этот конкретный вариант использования и преднамеренно сломать его.