2012-03-24 17 views
1

16バイトの配列をアトミックに設定するWindows APIがあるのだろうか?16バイト配列をアトミックに設定するWindows APIはありますか?

この操作を実装するために、クリティカルセクションまたはミューテックスを導入するのは本当に嫌いです。だから私は簡単な解決策を見つけようとしています。

PS。この16バイトの配列は、ワーカースレッドから書き込むことができ、主にメインスレッドから読み込むことができるため、これが必要です。

+1

16バイト*配列*?無限の数の16バイト要素を意味しますか?これは基本的に、存在しない任意の大きなチャンクを設定できるアトミックな操作を意味します。 –

+0

クリティカルセクションコードを書き込むのにどれくらい時間がかかりますか? 5分以内ですか?あなたの質問のPSは単なる役に立たない情報です。 – Nawaz

+0

@John Calsbeekいいえ、私はそれを意味しませんでした。私はそれらの16バイトを原子的にコピーすることを意味しました。 – ahmd0

答えて

4

以下はすべて、64ビットx86_64アーキテクチャを前提としています。私はあなたが求めたものは32ビットx86では不可能だと考えています。

実際には2つのオプションがあります。最初のものは_InterlockedCompareExchange128で、これはLOCK CMPXCHG16Bに変換されます。これは連動操作であるため、それは_ReadWriteBarrierと同等のものを意味することを

__int64* dest = ...; 
__int64* orig = ...; 
unsigned char ok; 
do 
{ 
    __int64 high = dest[0]; 
    __int64 low = dest[1]; 
    ok = _InterlockedCompareExchange128(dest, high, low, orig); 
} 
while (!ok); 

注:これで16バイトのストアの機能を複製するには、このような何かをする必要があると思います。これは、通常、「アトミック」操作が意味するものです。

比較交換ではなく純粋なストアを使用する場合は、ハードウェア上の16バイトの整列されたストアに変換するものを使用できます。たとえば、MOVDQA命令は修飾されます。 C++では、それはこのような何かになりたい:あなたはSSE命令を回避するための理由がない限り

__m128i* dest = ...; 
_mm_mfence(); 
_mm_store_si128(dest, _mm_loadu_si128((__m128i*)&orig)); 
_mm_mfence(); 

を、私は2番目のバージョンは、より良い実行するかもしれないと思います。実際のニーズに応じて、2つのメモリバリアを緩和するかどうかを決めることもできます。

+0

非常にいいです、ありがとう! – ahmd0

+0

私は、2つのオブジェクト参照を保持し、CompareExchangedすることができます.netで "objectPair"型があったと思います。 32ビットマシンには32ビットのオブジェクト参照と64ビットの比較交換があり、64ビットのマシンには64ビットのオブジェクト参照がありますが、128ビットの比較交換があるため、.netオブジェクト参照のペアのCompareExchangeを許可します。 68020で見つかった真のダブル・コンペア・アンド・スワップ操作ほど有用ではありませんが、今日のハードウェアでは利用可能です。 – supercat

関連する問題