_ReadWriteBarrier
Microsoft 固有の仕様 →
強制的にメモリに呼び出しの時点で完了するには、読み取りと書き込み。
注意 |
---|
_ReadBarrier、 _WriteBarrierと _ReadWriteBarrier コンパイラ組み込みはコンパイラの並べ替えだけなります。読み取り順序と書き込み操作で CPU を回避するには、 MemoryBarrier のマクロを使用します。 |
void _ReadWriteBarrier(void);
必要条件
組み込み |
アーキテクチャ |
---|---|
_ReadWriteBarrier |
x86、 IPF、 x64 |
ヘッダー ファイル <intrin.h>
解説
_ReadBarrier、 _WriteBarrierと _ReadWriteBarrier の関数は Visual C++ コンパイラによって最適化されたマルチスレッド プログラムの正しい操作を確認できます。適切に最適化されたプログラムは、シングル スレッドで実行時に複数のスレッドでように実装する方法と同じ結果になります。
_ReadBarrier、 _WriteBarrier、または _ReadWriteBarrier の関数が実行するアプリケーションのポイントはメモリ バリアと呼ばれます。メモリ バリアは読み取り、書き込み、または両方になる場合があります。
アクセスは、最適化の一部としてメモリ バリアを越えてメモリの変数削除されたか、移動されることがあります。プロセス。その結果、スレッドが別のスレッドが変数の変更前の値を読み取ることが完了する前に別のスレッドが変数に新しい値を書き込むことを完了する、または新しい値を書き込みます場合があります。前にグローバル変数の変更前の値を読み取ります。
最適化されたプログラムが正しく動作することを確認するには、 _ReadWriteBarrier の関数の型変換がメモリに呼び出しの時点で完了するには、読み取りと書き込み。呼び出しの後に、別のスレッドの呼び出しを行ったスレッドがメモリに保留中の読み取りや書き込みがあります。という恐れせずにメモリにアクセスできます。メモリ バリアは、バリアに最適化のメモリ アクセスからバリア間のプロセスを最適化するために、コンパイラ、コンパイラを有効にします。
メモリ バリアでマークのメモリは 揮発性 (C++) のキーワードを示すメモリに似ています。ただし、メモリ バリアは読み取りと書き込みを全体的にはなく、プログラムの特定の時点で終了するように強制されるため、より効率的です。メモリ バリアが使用されている場合に発生する可能性がある最適化は変数が volatile で宣言されている場合は発生しません。
[!メモ]
Visual C++ コンパイラの旧バージョンでは、 _WriteBarrier の _ReadWriteBarrier と関数は、ローカルにのみ適用され、コール ツリーの最上位の関数には影響を与えませんいません。これらの関数は、コール ツリーの最上位に表示して実装されます。
影響を受けるメモリ
グローバル変数がメモリ バリアに影響されますが、ローカル変数は、通常は影響しません。したがって、ほとんどのローカル変数は、他のスレッドがアクセスできないため、保護を必要としません。変数は、メモリ バリアを使用して、次の 1 種類の要件を満たす影響されます:
変数は、グローバル変数です。
変数は C++ 例外処理を使用した場合は、構造化例外処理を使用する場合、または catch のブロックです __try、 __except、または __finally ブロックで使用されているローカル変数。詳細については、 /EHa の " を参照してください。
変数は volatileで宣言されたローカル変数です。
変数は現在の関数のアドレスでになんらかのエスケープするローカル変数です。たとえば、型の変数が別の関数への参照が渡されますまたはアドレスはグローバル変数に割り当てます。
変数は、ポインターを通じて間接的にアクセスし、逆参照ポインターは前の 1 種類の要件を満たします。最も一般的なケースは p がグローバル変数またはパラメーターの *p です。
使用例
// intrinsics_readwritebarrier.c
// compile with: /O2 -DNO_BARRIER
// This code contains an error--dereferencing a null pointer--
// which will be optimized away as a useless assignment.
// Omit the NO_BARRIER command line to activate the Write Barrier.
// With the barrier activated, the assignment is not optimized away
// and causes an access violation.
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>
#include <stdio.h>
#include <intrin.h>
#pragma intrinsic(_ReadWriteBarrier)
int x = 0;
__declspec(noinline) int f(int* p)
{
x = *p;
#ifndef NO_BARRIER
_ReadWriteBarrier();
#endif
x = 7;
return x;
}
// If code is EXCEPTION_ACCESS_VIOLATION it means an
// attempt to read from the NULL pointer we passed in, so
// we handle the exception.
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
if (code == EXCEPTION_ACCESS_VIOLATION)
{
printf_s("AV\n");
return EXCEPTION_EXECUTE_HANDLER;
}
// If not what we were looking for, we don't want to handle it.
return EXCEPTION_CONTINUE_SEARCH;
}
int main()
{
int nRet = 0;
__try
{
// Should return only if the first assignment is
// optimized away.
nRet = f(NULL);
printf_s("Assignment was optimized away!\n");
}
__except(filter(GetExceptionCode(), GetExceptionInformation()))
{
// We get here if an Access violation occurred.
printf_s("Access Violation: assignment was not optimized away.\n");
}
}