Share via


_WriteBarrier 

Microsoft Specific

Forces memory writes to complete and be correct according to program logic at the point of the call.

void _WriteBarrier(void);

Requirements

Intrinsic Architecture

_WriteBarrier

x86, IPF, x64

Header file <intrin.h>

Remarks

As part of its optimization algorithms, the Visual C++ compiler might reorder memory reads and writes in unpredictable ways between explicit accesses to a variable. As a result, the value of that variable might not have a predictable value between each explicit use of the variable. This could cause problems in multithreaded programming. _ReadWriteBarrier, _WriteBarrier, and _ReadBarrier are useful for multithreaded program logic that relies on variable values between explicit reads and writes.

At the point of the call, all shared variables can be accessed by another thread without fear that the write had not yet actually occurred or the variable's value was unexpectedly changed because an optimization.

Note   In past versions of the compiler, _WriteBarrier was enforced only locally and did not affect functions up the call tree. In Visual C++ 2005, _WriteBarrier is enforced all the way up the call tree. The results of the following example apply only to the current Visual C++ compiler.

Example

The following example is similar to that shown in _ReadWriteBarrier. In the function f two assignments are made 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 kept 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 only return 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!

END Microsoft Specific

See Also

Reference

_ReadBarrier
_ReadWriteBarrier
Compiler Intrinsics