2016-11-01 2 views
16

Как известно, std::atomic и volatile - это разные вещи.Является ли стандартный C++ 11 гарантией того, что `volatile atomic <T>` имеет и семантику (volatile + atomic)?

Есть 2 основных отличия:

  1. Две оптимизации может быть для std::atomic<int> a;, но не может быть для volatile int a;:

    • конденсированных операций: a = 1; a = 2; могут быть заменены на компилятор a = 2;
    • постоянное распространение: a = 1; local = a; может быть заменено компилятором на a = 1; local = 1;
  2. Изменение порядка обыкновенных операций чтения/записи по атомным/летучий операций:

    • для volatile int a; не может быть заказана любые летучие чтения/записи-операции. Но близкие обычные чтения/записи все еще могут быть переупорядочены вокруг изменчивых операций чтения/записи.
    • для std::atomic a; переназначения поблизости обычных чтения/записи ограничений, на основе барьера памяти, используемый для атомарной операции a.load(std::memory_order_...);

Т.е. volatile не вводят забор памяти, но std::atomic может это сделать.

Как хорошо описано в статье:

Например, std::atomic следует использовать для параллельных многопоточных программ (CPU-Core < -> CPU-Core), но volatile следует использовать для доступа к Mamory Mapped Regions на устройствах (CPU-Core < -> Устройство).


Но если требуется, и имеет необычную семантику и имеет какие-либо или все атомарность и/или заказ гарантий, необходимые для кодирования безблокировочного, т.е.если требуется volatile std::atomic<>, требуется по нескольким причинам:

  • заказа: для предотвращения изменения порядка обычные чтения/записи, например, для чтения из CPU-RAM, на который данные записаны с помощью устройств DMA-контроллер

Например:

char cpu_ram_data_written_by_device[1024]; 
device_dma_will_write_here(cpu_ram_data_written_by_device); 

// physically mapped to device register 
volatile bool *device_ready = get_pointer_device_ready_flag(); 

//... somewhere much later 
while(!device_ready); // spin-lock (here should be memory fence!!!) 
for(auto &i : cpu_ram_data_written_by_device) std::cout << i; 

пример:

char cpu_ram_data_will_read_by_device[1024]; 
device_dma_will_read_it(cpu_ram_data_written_by_device); 

// physically mapped to device register 
volatile bool *data_ready = get_pointer_data_ready_flag(); 

//... somewhere much later 
for(auto &i : cpu_ram_data_will_read_by_device) i = 10; 
data_ready=true; //spilling cpu_ram_data_will_read_by_device to RAM, should be memory fence 
  • атомного: чтобы гарантировать, что летучая операция будет атомной - то есть он будет состоять из одной операции вместо нескольких - т.е. одной 8-байтовой операции вместо двух 4-байтовых операций

Для этого Herb Sutter говорит о volatile atomic<T>, 8 января 2009: http://www.drdobbs.com/parallel/volatile-vs-volatile/212701484?pgno=2

Наконец, чтобы выразить переменный, и обладает необычной семантикой и имеют любого или все атомарность и/или заказ гарантии, необходимую для кодирование без блокировки, только стандарт стандарта ISO C++ 0x обеспечивает прямой способ для его использования: изменчивый атомный.

Но делать современные стандартов C++ 11 (не C++ 0x проект), C++ 14 и C++ 17 гарантирует, что volatile atomic<T> имеет и семантику (летучую + атомную)?

volatile atomic<T> гарантирует самые строгие гарантии как от летучих, так и от атомных?

  1. Как и в volatile: Резкий конденсированную операцию и постоянное-распространение, как описано в начале вопроса
  2. Как и в std::atomic: представляет заборы памяти, чтобы обеспечить упорядочение, разлив, и быть атомарным.

И мы можем сделать reinterpret_cast от volatile int *ptr; до volatile std::atomic<int>*?

+0

Позвольте мне кратко рассказать. 'volatile atomic ' over 'atomic ' и почему вы хотите сделать 'reinterpret_cast'? Это, вероятно, будет работать, но не гарантируется. – DeiDei

+3

У вас не может быть 'std :: atomic ', потому что волатильный тип не является тривиально копируемым. – Brian

+0

@Brian Да, вы правы. Удалено о 'std :: atomic '. – Alex

ответ

3

Да, это так.

Раздел 29.6.5, "Требования к операциям на атомных типов"

Многие операции нестабильны квалифицированные. Семантика "volatile as register" не изменилась в стандарте. Эта квалификация означает, что волатильность сохраняется при применении этих операций к неустойчивым объектам.

Я проверил рабочие проекты с 2008 по 2016 год, и тот же текст есть во всех них. Поэтому он должен применять C++ 11, C++ 14 и C++ 17.

Смежные вопросы