_WriteBarrier
Microsoft Specific
Forces writes to memory to complete at the point of the call.
Warning
The _ReadBarrier, _WriteBarrier, and _ReadWriteBarrier compiler intrinsics prevent only compiler re-ordering. To prevent the CPU from re-ordering read and write operations, use the MemoryBarrier macro.
void _WriteBarrier(void);
Requirements
Intrinsic |
Architecture |
---|---|
_WriteBarrier |
x86, IPF, x64 |
Header file <intrin.h>
Remarks
The _ReadBarrier, _WriteBarrier, and _ReadWriteBarrier functions help ensure the proper operation of multithreaded programs that are optimized by the Visual C++ compiler. A correctly optimized program yields the same results when it executes on multiple threads as when it executes on a single thread.
To help ensure that the optimized program operates correctly, the _WriteBarrier function forces writes to memory to complete at the point of the call. After the call, other threads can access the memory without fear that the thread that made the call might have a pending write to the memory. For more information, see the remarks in _ReadWriteBarrier.
Note
In past versions of the Visual C++ compiler, the _ReadWriteBarrier and _WriteBarrier functions were enforced only locally and did not affect functions up the call tree. In Visual C++ 2005 and later, these functions are enforced all the way up the call tree.
Example
The following example is similar to that shown in _ReadWriteBarrier. The function f makes two assignments to the local variable x. Without the _WriteBarrier the first assignment is optimized away as a useless assignment. With the _WriteBarrier in place both assignments are retained and an access violation occurs when the first assignment attempts to dereference a NULL pointer.
// intrinsics_writebarrier.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(_WriteBarrier)
int x = 0;
__declspec(noinline) int f(int* p)
{
x = *p;
#ifndef NO_BARRIER
_WriteBarrier();
#endif
x = 7;
return x;
}
// If code is EXCEPTION_ACCESS_VIOLATION it should be the
// 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()
{
__try
{
// Should return only if the first assignment is
// optimized away.
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");
}
}
Sample Output
Without /DNO_BARRIER:
AV
Access Violation: assignment was not optimized away.
With /DNO_BARRIER:
Assignment was optimized away!