2016-11-01 4 views
16

知られているように、std::atomicvolatileは異なるものです。標準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;
    • ため

      • 任意の揮発性の読み取り/書き込み操作を並べ替えることができません。普通の
    • の並べ替えは、/は、揮発性/アトミック操作間で読み書きを行います。しかし、近くの通常の読み取り/書き込みは、揮発性の読み取り/書き込みの前後で並べ替えることができます。

    • 近く通常のstd::atomic a;並べ替えのために/をアトミック操作a.load(std::memory_order_...);

即ちために使用されるメモリバリアに基づいて制限読み書きvolatileメモリフェンスを導入していませんが、std::atomicが可能です。

も資料に記載されているように

例えば、std::atomicは、同時マルチスレッドプログラム(CPUコア< - > CPUコア)に使用する必要がありますが、デバイス上のMamory Mapped Regionへのアクセスにはvolatileを使用してください(CPUコア< - >デバイス)。必要に応じて


しかし、両方のは異例の意味を持っており、および/またはロックフリー符号化のために必要な保証を注文する、すなわち、原子のいずれかまたは全てを持っていますvolatile std::atomic<>を必要に応じて、いくつかの理由のために必要:

  • を注文:通常の並べ替えを防止するために、データがデバイスDMAコントローラを使用して書き込まれたCPU-RAMからの読み出しのために/は、例えば、読み書き例えば

:がこぼれる

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 
  • 原子:揮発性動作がアトミックであることを保証しますつまり、複数の代わりに1回の操作、つまり2つの4バイト操作の代わりに1つの8バイト操作で構成されます。

このために、ハーブサッター約volatile atomic<T>、2009年1月8日言った:http://www.drdobbs.com/parallel/volatile-vs-volatile/212701484?pgno=2最後に

、両方が異例の意味を持っており、 いずれかまたはアトミックの全ておよび/または のために必要な保証を注文を持つ変数を表現しますロックフリーのコーディングでは、ISO C++ 0xドラフトスタンダードのみが直接 という綴り方を提供しています。

しかし、やる現代標準C++ 11(ないC++ 0xのドラフト)、C++ 14、及びvolatile atomic<T>は(揮発性+原子)の両方の意味を持っていることをC++ 17保証?

volatile atomic<T>は、volatileとatomicの両方から最も厳しい保証をしていますか? volatileのよう

  1. std::atomicのように質問
  2. の冒頭に記載したように溶融操作および定数伝播を回避するには:こぼれ、順序を提供するために、メモリフェンスを導入し、アトミックです。

reinterpret_castvolatile int *ptr;からvolatile std::atomic<int>*までは可能ですか?

+0

私は短いコメントを投げさせてください。 'volatile atomic 'を 'atomic 'に置き換え、なぜ 'reinterpret_cast'をやりたいのですか?おそらく動作しますが、保証されません。 – DeiDei

+3

揮発性の型は簡単にコピーできないため、 'std :: atomic 'は使用できません。 – Brian

+0

@Brianはい、あなたは正しいです。 'std :: atomic 'について削除されました。 – Alex

答えて

3

はい、あります。

多くの操作

セクション29.6.5、"原子型での操作のための要件は、" volatile修飾されています。 「デバイスレジスタとしての揮発性」セマンティクスは、標準では変更されていません。この資格は、これらの操作を揮発性のオブジェクトに適用するとボラティリティが保持されることを意味します。

2008年から2016年までの作業草案を確認しましたが、すべて同じテキストが含まれています。したがって、C++ 11、C++ 14、およびC++ 17を適用する必要があります。

関連する問題